<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>个人博客</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta property="og:type" content="website">
<meta property="og:title" content="个人博客">
<meta property="og:url" content="https://gitee.com/wieldy/bailment-blog/page/2/index.html">
<meta property="og:site_name" content="个人博客">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/bailment-blog/atom.xml" title="个人博客" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/bailment-blog/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/bailment-blog/css/style.css">

  
    
<link rel="stylesheet" href="/bailment-blog/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 6.3.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/bailment-blog/" id="logo">个人博客</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/bailment-blog/">Home</a>
        
          <a class="main-nav-link" href="/bailment-blog/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/bailment-blog/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="https://gitee.com/wieldy/bailment-blog"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main">
  
    <article id="post-2.net" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/bailment-blog/2022/03/29/2.net/" class="article-date">
  <time class="dt-published" datetime="2022-03-29T14:12:00.000Z" itemprop="datePublished">2022-03-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/bailment-blog/2022/03/29/2.net/">2.net</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="http1-0"><a href="#http1-0" class="headerlink" title="http1.0"></a>http1.0</h2><ul>
<li>每个请求都需要建立一个tcp链接</li>
<li>三次握手、慢启动问题</li>
<li>tcp断开的问题：不会立即断开需要等待一段时间，在关闭tcp链接， 占用大量端口，可能会导致端口用尽</li>
</ul>
<h2 id="http1-1"><a href="#http1-1" class="headerlink" title="http1.1"></a>http1.1</h2><blockquote>
<p>keep-alive</p>
</blockquote>
<p>在1个tcp链接上可以完成多个http的事物 （content-length来区分请求体） 可以复用链接 （没有每次都慢启动）<br>请求都是串行的 （在同一个tcp通道中， 为什么不能是并发？ 因为http他没有序号，也就意味着不能重组，响应和请求得有一个映射关系）<br>管线化，优化串行问题，整批提交http请求，响应还是要按照顺序来返回 ， http的队头阻塞问题 head-of-line-blocking (浏览器没有开启)<br>1个域名可以链接多个tcp链接 chrome是6个 （并发操作） 带宽竞争 固定的带宽 6个慢启动 （通过多创建几个域名来解决这些问题，域名多了要做dns解析，文件合并，雪碧图，减少请求，如果文件打包到一起，文件太大，下载慢，缓存）  http1.1增加了缓存</p>
<blockquote>
<p>http1.1 虽然增加了keep-alive (缺点 http队头阻塞,tcp队头阻塞问题，不安全明文传输，http是文本传输协议)</p>
</blockquote>
<h2 id="https"><a href="#https" class="headerlink" title="https"></a>https</h2><p>https &#x3D; http + ssl&#x2F;tls v3 改名成了 tls  (加密，让数据安全的传输)</p>
<ul>
<li><p>1.数据不能被篡改 （http无状态的） 将内容进行摘要，到时候校验摘要的内容 (SHA256)</p>
</li>
<li><p>2.让传输的数据进行加密</p>
</li>
<li><p>加密算法  对称加密AES   非对称加密RSA</p>
<ul>
<li><p>方案1： 通过客户端主动发请求来索要密钥， 密钥如果在网络中传输会被截获 （能不能别传递密钥这样不安全）</p>
</li>
<li><p>方案2: 公钥和私钥 （公钥加密，私钥解密，私钥加密，公钥解密） 服务端和客户端同时产生一对密钥（服务端的私钥和公钥，客户端的私钥个公钥），互相把公钥共享给对方，公钥加密只能私钥解密，如果出现中间人也无法解密内容。 这样就安全了？ 你怎么知道对方是真人？ 我们无法校验公钥的授予方</p>
</li>
<li><p>方案3： 优化加密方式，服务端生成一对公钥和私钥，将公钥发送给客户端，客户端生成会话密钥，用服务端提供的公钥来进行加密，传输给服务器，服务器可以解密，解密后可以拿到会话密钥，后续的操作可以采用对称加密来通信 （服务端发过来的公钥我不知是不是真的）</p>
</li>
<li><p>证书，证明你是谁，来确定公钥的发送者</p>
</li>
<li><p>ca证书，让公钥变的更信任，第三方可信任的（机构不能造假）服务端生成一对公钥和私钥，将公钥交给第三方机构，他会帮你提供一个证书<br>  （证书要包含你的“公钥”，有效期，颁发机构信息，摘要用的什么算法） -》 将证书进行一个摘要（内容小）&#x3D;》 机构也内置了一对密钥 用私钥来加密你的摘要</p>
</li>
<li><p>用户电脑中内置ca公钥，ca来解密，解密后将证书再次摘要，如果两次结果一致，就是可信任的，会通过公钥拿到证书中的公钥</p>
</li>
<li><p>服务端将公钥放到证书中， 证书会做非对称加密，客户端可以（验签）验证证书的来源，如果靠谱则可以去到服务端的公钥</p>
</li>
<li><p>付费： 你要提供一个公钥，交给付费机构，付费机构就会给你个证书，你可以将证书发送给客户端即可</p>
</li>
</ul>
</li>
</ul>
<blockquote>
<p>采用了对城和非对称 两种方式进行加密，保证公钥是服务端发送的引入了ca中</p>
</blockquote>
<p>tls 握手<br>client hello  我有哪些加密的方式（密钥交换的时候用什么方式，对称加密用什么，非对称加密用什么，摘要算法服务端）</p>
<ul>
<li>client random -&gt; 服务端<br>server hello    </li>
<li>server random -&gt; 给客户端  采用密钥的方式来通信</li>
</ul>
<blockquote>
<p>主要的目的就是，告诉对方加密的方式（如果方式固定的话 就不用这次rtt了 1.3）</p>
</blockquote>
<ul>
<li><p>server 给你一个证书 并且生成一个params 交给客户端</p>
</li>
<li><p>client 生成一个params 交给服务端</p>
</li>
<li><p>client random + server random + client params + serverParams  -&gt; 会话密钥 （后续用于加密内容的也就是做对称加密的密钥）</p>
</li>
<li><p>“DECHE” 算法 用于交换密钥  密钥交换算法，客户端和服务端通过两个参数 ，可以创建出一个会话密钥来，通过这个会话密钥可以加密内容，虽然参数暴露到了网络中，但是无法通过这两个参数 来计算出这个会话密钥</p>
</li>
</ul>
<blockquote>
<p>tls 握手过程 1） 协商中用到的加密算法  2） 交换密钥参数，生成会话密钥  3） 通过这个会话密钥加密通信</p>
</blockquote>
<h2 id="http2-0"><a href="#http2-0" class="headerlink" title="http2.0"></a>http2.0</h2><ul>
<li>http1.1 有什么问题？ 纯文本格式 ， 采用\r\n\r\n来解析内容， 在解析的过程中会有歧义 connect Connect 性能比较差， http不再采用文本格式，采用纯的二进制的方式来通信</li>
<li>http1.1 不能乱序收发 ，在请求的时候我们可以将数据直接放到管道中传输（流stream 二进制帧（流的id）） 可以直接将不同的请求塞到一个流中传输</li>
<li>http1.1 要开启多个tcp链接 消耗性能</li>
<li>多个tcp 三次握手  慢启动….</li>
</ul>
<p>http2.0 优化</p>
<ul>
<li><p>二进制方式传输</p>
</li>
<li><p>一个域名只建立一个tcp链接，一个链接中可以同时传输不同请求（http中的队头阻塞问题）， 传输内容考的是流（模型，传递的是帧，帧就是传输的单位）</p>
</li>
<li><p>二进制分针层，流量控制，优先级处理，服务端推送</p>
</li>
<li><p>头部在http1.1中 只能压缩内容 gzip br deflate, cookie(domain path) 固定的字段 content-length host… http2 中做了头部压缩 hpack</p>
</li>
<li><p>html 1&#x2F;3  css 1&#x2F;3   js 1&#x2F;3  -&gt; 流  如果中间包丢失了 后面需要前面的传递完成后再去重新发送</p>
</li>
<li><p>头部压缩  索引表 （动态表，静态表）  哈夫曼编码 （可以让编码的结果没有歧义、而且编码的结果小）</p>
</li>
</ul>
<p>如何编码 让常用的字符编码出的结果短一点 ，让不常用的长一些</p>
<p>编码的问题 a-&gt; 0 b -&gt; 1 c-&gt; 10 d-&gt; 11</p>
<p>a-&gt; 00<br>b-&gt; 01<br>c-&gt; 10<br>d-&gt; 11</p>
<p>6个字符进行编码 我需要用  111  -》 8  每个字节都得用3个位来表示</p>
<p>000<br>001<br>010<br>011<br>100<br>111<br>110<br>101</p>
<p>46 * 3 &#x3D; 138个位来表示</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> http2 = <span class="built_in">require</span>(<span class="string">&#x27;node:http2&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;node:fs&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> server = http2.<span class="title function_">createSecureServer</span>(&#123;</span><br><span class="line">  <span class="attr">key</span>: fs.<span class="title function_">readFileSync</span>(<span class="string">&#x27;localhost-privkey.pem&#x27;</span>),</span><br><span class="line">  <span class="attr">cert</span>: fs.<span class="title function_">readFileSync</span>(<span class="string">&#x27;localhost-cert.pem&#x27;</span>)</span><br><span class="line">&#125;);</span><br><span class="line">server.<span class="title function_">on</span>(<span class="string">&#x27;error&#x27;</span>, <span class="function">(<span class="params">err</span>) =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">error</span>(err));</span><br><span class="line"></span><br><span class="line">server.<span class="title function_">on</span>(<span class="string">&#x27;stream&#x27;</span>, <span class="function">(<span class="params">stream, headers</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// 流是双工的</span></span><br><span class="line">  stream.<span class="title function_">respond</span>(&#123; <span class="comment">// headers frame</span></span><br><span class="line">    <span class="string">&#x27;content-type&#x27;</span>: <span class="string">&#x27;text/html; charset=utf-8&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;:status&#x27;</span>: <span class="number">200</span></span><br><span class="line">  &#125;);</span><br><span class="line">  stream.<span class="title function_">end</span>(<span class="string">&#x27;&lt;h1&gt;Hello World&lt;/h1&gt;&#x27;</span>); <span class="comment">// data frame</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">server.<span class="title function_">listen</span>(<span class="number">8443</span>);</span><br></pre></td></tr></table></figure>

<p><a href="/images/2.%E7%BD%91%E7%BB%9C.pdf">网络目录</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://gitee.com/wieldy/bailment-blog/2022/03/29/2.net/" data-id="cljmgj1et0005zc9jhyk2ef3z" data-title="2.net" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-Promise" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/bailment-blog/2022/03/29/Promise/" class="article-date">
  <time class="dt-published" datetime="2022-03-29T14:12:00.000Z" itemprop="datePublished">2022-03-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/bailment-blog/2022/03/29/Promise/">Promise</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <ul>
<li>高阶函数<br>什么是高阶函数：1) 一个函数满足参数或者返回值是函数，那么这个函数就是高阶函数</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">core</span>(<span class="params">a,b,c</span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;核心代码&#x27;</span>,a,b,c)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Function</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">before</span> = <span class="keyword">function</span>(<span class="params">cb</span>)&#123; <span class="comment">//  2) 一个函数的参数是一个函数也是高阶函数</span></span><br><span class="line">    <span class="comment">// 箭头函数的特点是： 1） 没有this 2) 没有arguments  3）没有prototype</span></span><br><span class="line">    <span class="comment">// this = core</span></span><br><span class="line">    <span class="keyword">return</span> <span class="function">(<span class="params">...args</span>)=&gt;</span>&#123; <span class="comment">// 1） 一个函数返回一个函数那么这个函数就是高阶函数</span></span><br><span class="line">        <span class="title function_">cb</span>()</span><br><span class="line">        <span class="title function_">this</span>(...args);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> newCore = core.<span class="title function_">before</span>(<span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;before&#x27;</span>)</span><br><span class="line">&#125;)</span><br><span class="line"><span class="title function_">newCore</span>(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>); <span class="comment">// 对原来的方法进行了扩展</span></span><br></pre></td></tr></table></figure>

<ul>
<li><p>高阶函数的应用</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 函数参数的预置 将函数的参数 进行一个保留 (闭包)</span></span><br><span class="line"><span class="comment">// 闭包就是函数定义的作用域和执行的作用域不是同一个 此时就会产生闭包 (靠谱)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 函数的柯里化   偏函数  都是基于高阶函数来实现的 </span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 判断类型 有常见的4种方式</span></span><br><span class="line"><span class="comment">// typeof 可以判断基本类型，  typeof null === &#x27;object&#x27;</span></span><br><span class="line"><span class="comment">// instanceof 可以判断某个类型是否属于谁的实例</span></span><br><span class="line"><span class="comment">// Object.prototype.toString 需要再对象的原型中在找到方法</span></span><br><span class="line"><span class="comment">// constructor [].constrotor Array  &#123;&#125;.constructor  Object</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">function isType(typing,val)&#123;</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    return (Object.prototype.toString.call(val)) === `[object $&#123;typing&#125;]`</span></span><br><span class="line"><span class="comment">&#125;</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">// 可不可以将参数预置到函数内部</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">console.log(isType(&#x27;Object&#x27;,&#123;&#125;))</span></span><br><span class="line"><span class="comment">console.log(isType(&#x27;String&#x27;,&#x27;abc&#x27;))</span></span><br><span class="line"><span class="comment">console.log(isType(&#x27;Number&#x27;,123))</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">isType</span>(<span class="params">typing</span>)&#123;</span><br><span class="line">    <span class="comment">// Number</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">function</span> <span class="title function_">isNumber</span>(<span class="params">val</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="title class_">Object</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">toString</span>.<span class="title function_">call</span>(val)) === <span class="string">`[object <span class="subst">$&#123;typing&#125;</span>]`</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> utils = &#123;&#125;;</span><br><span class="line">[<span class="string">&#x27;Number&#x27;</span>,<span class="string">&#x27;Boolean&#x27;</span>,<span class="string">&#x27;String&#x27;</span>].<span class="title function_">forEach</span>(<span class="function"><span class="params">type</span> =&gt;</span> &#123;</span><br><span class="line">    utils[<span class="string">`is<span class="subst">$&#123;type&#125;</span>`</span>] = <span class="title function_">isType</span>(type)</span><br><span class="line">&#125;);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(utils.<span class="title function_">isNumber</span>(<span class="string">&#x27;abc&#x27;</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment">// isType方法的范围比较大  -》 小范围isNumber （函数柯里化，将范围具体化 可以实现批量传递参数  通用的函数科里化的实现）</span></span><br><span class="line"><span class="comment">// 函数反科里化  Object.prototype.toString.call(val)  =&gt; toString()</span></span><br><span class="line"><span class="comment">// 高阶函数的作用 1） 可以扩展功能  2） 可以对函数的参数进行预制参数</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>高阶函数解决异步问题</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 文件读取</span></span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&quot;fs&quot;</span>); <span class="comment">// 文件系统模块 filesystem</span></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&quot;path&quot;</span>); <span class="comment">// 路径模块 进行路径操作</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// fs.readFile()  默认path.resolve() 会根据执行的路径来解析绝对路径</span></span><br><span class="line"><span class="comment">// node中的异步api 回调的第一个参数 都是err-first</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// function cb(key,value)&#123;</span></span><br><span class="line"><span class="comment">//     obj[key] = value;</span></span><br><span class="line"><span class="comment">//     if(Reflect.ownKeys(obj).length === 2)&#123;</span></span><br><span class="line"><span class="comment">//         console.log(obj)</span></span><br><span class="line"><span class="comment">//     &#125;</span></span><br><span class="line"><span class="comment">// &#125;</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">after</span>(<span class="params">times,cb</span>)&#123;</span><br><span class="line">    <span class="keyword">let</span> obj = &#123;&#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">function</span> (<span class="params">key,value</span>)&#123;</span><br><span class="line">        obj[key]= value;</span><br><span class="line">        <span class="keyword">if</span>(--times == <span class="number">0</span>)&#123;</span><br><span class="line">            <span class="title function_">cb</span>(obj)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> cb = <span class="title function_">after</span>(<span class="number">2</span>,<span class="function">(<span class="params">data</span>)=&gt;</span>&#123; <span class="comment">// 只有在两次完成后后 才能得到结果，但是无法监控中间的过程 （发布订阅）</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data)</span><br><span class="line">&#125;)</span><br><span class="line">fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&quot;a.txt&quot;</span>), <span class="string">&quot;utf-8&quot;</span>, <span class="keyword">function</span> (<span class="params">err,data</span>) &#123;</span><br><span class="line">    <span class="title function_">cb</span>(<span class="string">&#x27;msg&#x27;</span>,data);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&quot;b.txt&quot;</span>), <span class="string">&quot;utf-8&quot;</span>, <span class="keyword">function</span> (<span class="params">err,data</span>) &#123;</span><br><span class="line">    <span class="title function_">cb</span>(<span class="string">&#x27;age&#x27;</span>,data);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 例如前端 并发ajax ，我们需要等待多个异步请求都完成后 将结果拿到渲染页面</span></span><br><span class="line"><span class="comment">// 同步 异步回调的执行结果</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 异步方法 在处理错误的情况时  必须通过回调的参数来处理</span></span><br></pre></td></tr></table></figure></li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 文件读取</span></span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&quot;fs&quot;</span>); <span class="comment">// 文件系统模块 filesystem</span></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&quot;path&quot;</span>); <span class="comment">// 路径模块 进行路径操作</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// fs.readFile()  默认path.resolve() 会根据执行的路径来解析绝对路径</span></span><br><span class="line"><span class="comment">// node中的异步api 回调的第一个参数 都是err-first</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// function cb(key,value)&#123;</span></span><br><span class="line"><span class="comment">//     obj[key] = value;</span></span><br><span class="line"><span class="comment">//     if(Reflect.ownKeys(obj).length === 2)&#123;</span></span><br><span class="line"><span class="comment">//         console.log(obj)</span></span><br><span class="line"><span class="comment">//     &#125;</span></span><br><span class="line"><span class="comment">// &#125;</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">after</span>(<span class="params">times,cb</span>)&#123;</span><br><span class="line">    <span class="keyword">let</span> obj = &#123;&#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">function</span> (<span class="params">key,value</span>)&#123;</span><br><span class="line">        obj[key]= value;</span><br><span class="line">        <span class="keyword">if</span>(--times == <span class="number">0</span>)&#123;</span><br><span class="line">            <span class="title function_">cb</span>(obj)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> cb = <span class="title function_">after</span>(<span class="number">2</span>,<span class="function">(<span class="params">data</span>)=&gt;</span>&#123; <span class="comment">// 只有在两次完成后后 才能得到结果，但是无法监控中间的过程 （发布订阅）</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data)</span><br><span class="line">&#125;)</span><br><span class="line">fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&quot;a.txt&quot;</span>), <span class="string">&quot;utf-8&quot;</span>, <span class="keyword">function</span> (<span class="params">err,data</span>) &#123;</span><br><span class="line">    <span class="title function_">cb</span>(<span class="string">&#x27;msg&#x27;</span>,data);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&quot;b.txt&quot;</span>), <span class="string">&quot;utf-8&quot;</span>, <span class="keyword">function</span> (<span class="params">err,data</span>) &#123;</span><br><span class="line">    <span class="title function_">cb</span>(<span class="string">&#x27;age&#x27;</span>,data);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 例如前端 并发ajax ，我们需要等待多个异步请求都完成后 将结果拿到渲染页面</span></span><br><span class="line"><span class="comment">// 同步 异步回调的执行结果</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 异步方法 在处理错误的情况时  必须通过回调的参数来处理</span></span><br></pre></td></tr></table></figure>

<ul>
<li><p>发布订阅模式</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 发布 （触发功能） &amp; 订阅（订阅一些功能）</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&quot;fs&quot;</span>); <span class="comment">// 文件系统模块 filesystem</span></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&quot;path&quot;</span>); <span class="comment">// 路径模块 进行路径操作</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> events = &#123;</span><br><span class="line">    <span class="attr">_obj</span>:&#123;&#125;,</span><br><span class="line">    <span class="attr">_arr</span>:[], <span class="comment">// 订阅中心，将所有的事，都订阅到数组中</span></span><br><span class="line">    <span class="title function_">on</span>(<span class="params">callback</span>)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_arr</span>.<span class="title function_">push</span>(callback);</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">emit</span>(<span class="params">key,value</span>)&#123; <span class="comment">// 事情发生后，来依次触发回调</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_obj</span>[key] = value;</span><br><span class="line"></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_arr</span>.<span class="title function_">forEach</span>(<span class="function"><span class="params">cb</span>=&gt;</span> <span class="title function_">cb</span>(<span class="variable language_">this</span>.<span class="property">_obj</span>))</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 可以订阅多个</span></span><br><span class="line">events.<span class="title function_">on</span>(<span class="function">()=&gt;</span>&#123; <span class="comment">// 监控每次触发的逻辑</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;读取完毕后机会触发&#x27;</span>)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">events.<span class="title function_">on</span>(<span class="function">(<span class="params">data</span>)=&gt;</span>&#123; <span class="comment">// 监控所有数据读取完毕</span></span><br><span class="line">    <span class="keyword">if</span>(<span class="title class_">Reflect</span>.<span class="title function_">ownKeys</span>(data).<span class="property">length</span> === <span class="number">2</span>)&#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;数据全部读取完毕&#x27;</span>,data)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line">fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&quot;a.txt&quot;</span>), <span class="string">&quot;utf-8&quot;</span>, <span class="keyword">function</span> (<span class="params">err,data</span>) &#123;</span><br><span class="line">    events.<span class="title function_">emit</span>(<span class="string">&#x27;msg&#x27;</span>,data);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&quot;b.txt&quot;</span>), <span class="string">&quot;utf-8&quot;</span>, <span class="keyword">function</span> (<span class="params">err,data</span>) &#123;</span><br><span class="line">    events.<span class="title function_">emit</span>(<span class="string">&#x27;age&#x27;</span>,data);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">/// 通过发布订阅来实现解耦合， 灵活，但是触发是需要用户自己触发的</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 观察者模式是基于发布订阅模式的  我们数据变化后可以自动通知触发发布 （vue 响应式原理）</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>观察者模式</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Subject</span> &#123; <span class="comment">// 被观察者</span></span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name</span>)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">name</span> = name</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_arr</span> = [];</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">state</span> = <span class="string">&#x27;很开心的&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">attach</span>(<span class="params">o</span>)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_arr</span>.<span class="title function_">push</span>(o); <span class="comment">// 订阅</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">setState</span>(<span class="params">newState</span>)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">state</span> = newState;</span><br><span class="line">        <span class="comment">// 宝宝状态变化了 会通知观察者更新，将自己传入过去</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_arr</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">o</span>)=&gt;</span>o.<span class="title function_">update</span>(<span class="variable language_">this</span>)); <span class="comment">// 发布</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Observer</span> &#123; <span class="comment">// 观察者</span></span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">name</span>)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">name</span> = name</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">update</span>(<span class="params">s</span>)&#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>.<span class="property">name</span> + <span class="string">&#x27;:&#x27;</span> + s.<span class="property">name</span> +s.<span class="property">state</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> o1 = <span class="keyword">new</span> <span class="title class_">Observer</span>(<span class="string">&#x27;爸爸&#x27;</span>)</span><br><span class="line"><span class="keyword">let</span> o2 = <span class="keyword">new</span> <span class="title class_">Observer</span>(<span class="string">&#x27;妈妈&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> s = <span class="keyword">new</span> <span class="title class_">Subject</span>(<span class="string">&#x27;宝宝&#x27;</span>); <span class="comment">// 创建一个被观察者</span></span><br><span class="line">s.<span class="title function_">attach</span>(o1) <span class="comment">// 订阅</span></span><br><span class="line">s.<span class="title function_">attach</span>(o2)</span><br><span class="line">s.<span class="title function_">setState</span>(<span class="string">&#x27;有人打我了&#x27;</span>)</span><br><span class="line"><span class="comment">//  发布订阅 用户要手动订阅 手动发布</span></span><br><span class="line"><span class="comment">// 观察者模式 是基于发布订阅的，主动的。 状态变化 主动通知</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>Promise</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="variable constant_">PENDING</span> = <span class="string">&quot;PENDING&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">FULFILLED</span> = <span class="string">&quot;FULFILLED&quot;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">REJECTED</span> = <span class="string">&quot;REJECTED&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 为了所有人promise 可以互相调用，所以所有的promise都要遵循这个规则</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">resolvePromise</span>(<span class="params">promise2, x, resolve, reject</span>) &#123;</span><br><span class="line">  <span class="comment">// 这个方法处理的会严谨一些，保证所有人的promise 都可以互相调用</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// If promise and x refer to the same object, reject promise with a TypeError as the reason.</span></span><br><span class="line">  <span class="comment">// 如果x 和 promise2 引用的是同一个对象，那么promise2 要等待x执行完毕</span></span><br><span class="line">  <span class="comment">// x是一个promise，而且永远不会成功和失败，那么就会在这里等待</span></span><br><span class="line">  <span class="keyword">if</span> (x === promise2)</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">reject</span>(<span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&quot;Chaining cycle detected for promise&quot;</span>));</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 我如何知道x是不是promise</span></span><br><span class="line">  <span class="keyword">if</span> ((<span class="keyword">typeof</span> x === <span class="string">&quot;object&quot;</span> &amp;&amp; x !== <span class="literal">null</span>) || <span class="keyword">typeof</span> x === <span class="string">&quot;function&quot;</span>) &#123;</span><br><span class="line">    <span class="comment">// 有可能是promise</span></span><br><span class="line">    <span class="comment">// Let then be x.then</span></span><br><span class="line">    <span class="keyword">let</span> called = <span class="literal">false</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="keyword">let</span> then = x.<span class="property">then</span>; <span class="comment">// then方法可能是通过defineProperty来进行定义的</span></span><br><span class="line">      <span class="keyword">if</span> (<span class="keyword">typeof</span> then === <span class="string">&quot;function&quot;</span>) &#123;</span><br><span class="line">        <span class="comment">// 是promise  &#123;then:function()&#123;&#125;&#125;</span></span><br><span class="line">        then.<span class="title function_">call</span>(</span><br><span class="line">          x,</span><br><span class="line">          <span class="function">(<span class="params">y</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">// x.then</span></span><br><span class="line">            <span class="comment">// 为了防止promise解析后的结果依旧是promise，所以需要递归解析</span></span><br><span class="line">            <span class="keyword">if</span> (called) <span class="keyword">return</span>;</span><br><span class="line">            called = <span class="literal">true</span>;</span><br><span class="line">            <span class="title function_">resolvePromise</span>(promise2, y, resolve, reject);</span><br><span class="line">          &#125;,</span><br><span class="line">          <span class="function">(<span class="params">r</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (called) <span class="keyword">return</span>;</span><br><span class="line">            called = <span class="literal">true</span>;</span><br><span class="line">            <span class="title function_">reject</span>(r);</span><br><span class="line">          &#125;</span><br><span class="line">        );</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="comment">// 就是一个对象或者函数  &#123;a:1&#125;  function()&#123;&#125;</span></span><br><span class="line">        <span class="title function_">resolve</span>(x);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">      <span class="keyword">if</span> (called) <span class="keyword">return</span>;</span><br><span class="line">      called = <span class="literal">true</span>;</span><br><span class="line">      <span class="title function_">reject</span>(e);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="title function_">resolve</span>(x); <span class="comment">// 普通值 直接将结果传递到下面就可以了</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Promise</span> &#123;</span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">executor</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">status</span> = <span class="variable constant_">PENDING</span>; <span class="comment">// 默认是等待态</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">value</span> = <span class="literal">undefined</span>; <span class="comment">/// 成功的原因</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">reason</span> = <span class="literal">undefined</span>; <span class="comment">// 失败的原因</span></span><br><span class="line"></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">onResolvedCallbacks</span> = [];</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">onRejectedCallbacks</span> = [];</span><br><span class="line">    <span class="comment">// promise调用then的时候 可能状态依旧是pending，那么我们需要将回调先存放起来</span></span><br><span class="line">    <span class="comment">// 等待过一会调用resolve时触发 onResolvedCallbacks 执行</span></span><br><span class="line">    <span class="comment">// 等待调用 reject时触发onRejectedCallbacks 执行</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">resolve</span> = (<span class="params">value</span>) =&gt; &#123;</span><br><span class="line">      <span class="comment">//只有状态是pending的时候 才可以修改状态 和 改变成功和失败的原因</span></span><br><span class="line"></span><br><span class="line">      <span class="keyword">if</span> (value <span class="keyword">instanceof</span> <span class="title class_">Promise</span>) &#123;</span><br><span class="line">        <span class="comment">// 递归解析的流程</span></span><br><span class="line">        <span class="keyword">return</span> value.<span class="title function_">then</span>(resolve, reject);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">status</span> === <span class="variable constant_">PENDING</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">status</span> = <span class="variable constant_">FULFILLED</span>;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">value</span> = value;</span><br><span class="line">        <span class="comment">// 成功调用成功的回调</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">onResolvedCallbacks</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">cb</span>) =&gt;</span> <span class="title function_">cb</span>());</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">reject</span> = (<span class="params">reason</span>) =&gt; &#123;</span><br><span class="line">      <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">status</span> === <span class="variable constant_">PENDING</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">status</span> = <span class="variable constant_">REJECTED</span>;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">reason</span> = reason;</span><br><span class="line">        <span class="comment">// 失败调用成功的回调</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">onRejectedCallbacks</span>.<span class="title function_">forEach</span>(<span class="function">(<span class="params">cb</span>) =&gt;</span> <span class="title function_">cb</span>());</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="comment">//  调用executor 会自动传入 resolve 和 reject</span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="title function_">executor</span>(resolve, reject);</span><br><span class="line">    &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">      <span class="title function_">reject</span>(e);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">catch</span>(errCallback) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="title function_">then</span>(<span class="literal">null</span>, errCallback);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="title function_">then</span>(<span class="params">onFulfilled, onRejected</span>) &#123;</span><br><span class="line">    onFulfilled = <span class="keyword">typeof</span> onFulfilled === <span class="string">&quot;function&quot;</span> ? onFulfilled : <span class="function">(<span class="params">v</span>) =&gt;</span> v;</span><br><span class="line">    onRejected =</span><br><span class="line">      <span class="keyword">typeof</span> onRejected === <span class="string">&quot;function&quot;</span></span><br><span class="line">        ? onRejected</span><br><span class="line">        : <span class="function">(<span class="params">e</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">throw</span> e;</span><br><span class="line">          &#125;;</span><br><span class="line">    <span class="keyword">let</span> promise2 = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// 调用then的时候 已经确定了是成功还是失败了</span></span><br><span class="line">      <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">status</span> === <span class="variable constant_">FULFILLED</span>) &#123;</span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">          <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">let</span> x = <span class="title function_">onFulfilled</span>(<span class="variable language_">this</span>.<span class="property">value</span>);</span><br><span class="line">            <span class="title function_">resolvePromise</span>(promise2, x, resolve, reject);</span><br><span class="line">          &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">            <span class="title function_">reject</span>(e);</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">status</span> === <span class="variable constant_">REJECTED</span>) &#123;</span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">          <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">let</span> x = <span class="title function_">onRejected</span>(<span class="variable language_">this</span>.<span class="property">reason</span>);</span><br><span class="line"></span><br><span class="line">            <span class="title function_">resolvePromise</span>(promise2, x, resolve, reject);</span><br><span class="line">          &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">            <span class="title function_">reject</span>(e);</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">status</span> === <span class="variable constant_">PENDING</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">onResolvedCallbacks</span>.<span class="title function_">push</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">          <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">              <span class="keyword">let</span> x = <span class="title function_">onFulfilled</span>(<span class="variable language_">this</span>.<span class="property">value</span>);</span><br><span class="line">              <span class="title function_">resolvePromise</span>(promise2, x, resolve, reject);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">              <span class="title function_">reject</span>(e);</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">onRejectedCallbacks</span>.<span class="title function_">push</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">          <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">              <span class="keyword">let</span> x = <span class="title function_">onRejected</span>(<span class="variable language_">this</span>.<span class="property">reason</span>);</span><br><span class="line">              <span class="title function_">resolvePromise</span>(promise2, x, resolve, reject);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">              <span class="title function_">reject</span>(e);</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;);</span><br><span class="line">        &#125;);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">return</span> promise2;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">static</span> <span class="title function_">resolve</span>(<span class="params">value</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="title function_">resolve</span>(value);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">static</span> <span class="title function_">reject</span>(<span class="params">reason</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="title function_">reject</span>(reason);</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">static</span> all = <span class="keyword">function</span> (<span class="params">values</span>) &#123;</span><br><span class="line">    <span class="comment">// promise 以第一个结果为准，其它的逻辑还是走，只是不采纳了</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// 并发是循环  串行递归</span></span><br><span class="line">      <span class="keyword">let</span> arr = [];</span><br><span class="line">      <span class="keyword">let</span> times = <span class="number">0</span>;</span><br><span class="line">      <span class="keyword">function</span> <span class="title function_">processData</span>(<span class="params">index, data</span>) &#123;</span><br><span class="line">        arr[index] = data; <span class="comment">// arr[2] = 1;</span></span><br><span class="line">        <span class="keyword">if</span> (++times === values.<span class="property">length</span>) &#123;</span><br><span class="line">          <span class="title function_">resolve</span>(arr);</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; values.<span class="property">length</span>; i++) &#123;</span><br><span class="line">        <span class="keyword">let</span> cur = values[i];</span><br><span class="line">        <span class="title class_">Promise</span>.<span class="title function_">resolve</span>(cur).<span class="title function_">then</span>(<span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span><br><span class="line">          <span class="title function_">processData</span>(i, data);</span><br><span class="line">        &#125;, reject);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">static</span> race = <span class="keyword">function</span> (<span class="params">values</span>) &#123;</span><br><span class="line">    <span class="comment">// promise 以第一个结果为准，其它的逻辑还是走，只是不采纳了</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// 并发是循环  串行递归</span></span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; values.<span class="property">length</span>; i++) &#123;</span><br><span class="line">        <span class="title class_">Promise</span>.<span class="title function_">resolve</span>(values[i]).<span class="title function_">then</span>(resolve, reject);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = <span class="title class_">Promise</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// promises-aplus-tests -g</span></span><br><span class="line"><span class="comment">// promises-aplus-tests 文件明</span></span><br><span class="line"><span class="title class_">Promise</span>.<span class="property">deferred</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">  <span class="comment">// deferred  all race catch ...</span></span><br><span class="line">  <span class="keyword">let</span> dfd = &#123;&#125;;</span><br><span class="line">  dfd.<span class="property">promise</span> = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    dfd.<span class="property">resolve</span> = resolve;</span><br><span class="line">    dfd.<span class="property">reject</span> = reject;</span><br><span class="line">  &#125;);</span><br><span class="line">  <span class="keyword">return</span> dfd;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 模块化规范 ， commonjs规范</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// promises-aplus-test</span></span><br><span class="line"></span><br></pre></td></tr></table></figure></li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://gitee.com/wieldy/bailment-blog/2022/03/29/Promise/" data-id="cljmgj1et0007zc9j2lqie5fo" data-title="Promise" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-async" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/bailment-blog/2022/03/29/async/" class="article-date">
  <time class="dt-published" datetime="2022-03-29T14:12:00.000Z" itemprop="datePublished">2022-03-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/bailment-blog/2022/03/29/async/">Async</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <ul>
<li>generator<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// generator 生成器 （生成迭代器的）</span></span><br><span class="line"><span class="comment">// promise 解决串行执行流程  并行执行流程  （因为promise依旧是基于回调的 onFulfilled onRejected）</span></span><br><span class="line"><span class="comment">// promise 并没有完全解决嵌套问题， 写异步代码的时候 还是不够优雅</span></span><br><span class="line"><span class="comment">// 就是让异步变成 更像同步变成  generator （数组的都有内置的迭代器）</span></span><br><span class="line"><span class="keyword">function</span>* <span class="title function_">read</span>(<span class="params"></span>) &#123; <span class="comment">// 默认会将一个函数分割成多个部分</span></span><br><span class="line">    <span class="keyword">yield</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">&#x27;vite&#x27;</span>;</span><br><span class="line">    <span class="keyword">yield</span> <span class="string">&#x27;node&#x27;</span>; <span class="comment">// 产卵，输出一个值 ，每次遇到yield就停止</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> it = <span class="title function_">read</span>(); <span class="comment">// it.throw() 抛出错误的   it.next()</span></span><br><span class="line"><span class="comment">// console.log(it.next()); // &#123;value:这次输出的值,done:是否执行完毕&#125;</span></span><br><span class="line"><span class="comment">// console.log(it.next());</span></span><br><span class="line"><span class="comment">// console.log(it.next());</span></span><br><span class="line"><span class="comment">// console.log(it.next());</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 生成器 和 普通函数不一样  需要加* 配合yeild 使用</span></span><br><span class="line"><span class="comment">// 返回的是迭代器，每次执行需要调用next方法， 产出的结果有 value,done</span></span><br><span class="line"><span class="comment">// 当遇到done为true的时候表示结束</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 什么叫类数组？  索引、有长度、能遍历</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 我们可以通过&quot;元编程&quot;来修改属性本身的逻辑 本身不能迭代我可以添加迭代方法，本身没有类型我可以添加类型</span></span><br><span class="line"><span class="keyword">let</span> likeArray = &#123;</span><br><span class="line">    <span class="number">0</span>: <span class="number">1</span>, <span class="number">1</span>: <span class="number">2</span>, <span class="number">2</span>: <span class="number">3</span>, <span class="attr">length</span>: <span class="number">3</span>,</span><br><span class="line">    get [<span class="title class_">Symbol</span>.<span class="property">toStringTag</span>]() &#123; <span class="comment">// 这个就表示重写了toString方法</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;MyArray&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    [<span class="title class_">Symbol</span>.<span class="property">iterator</span>]: <span class="keyword">function</span>* () &#123;</span><br><span class="line">        <span class="keyword">let</span> index = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">let</span> len = <span class="variable language_">this</span>.<span class="property">length</span></span><br><span class="line">        <span class="keyword">while</span> (len !== index) &#123;</span><br><span class="line">            <span class="keyword">yield</span> <span class="variable language_">this</span>[index++]</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/* [Symbol.iterator]() &#123; // 正在的函数</span></span><br><span class="line"><span class="comment">        let index = 0;</span></span><br><span class="line"><span class="comment">        return &#123;</span></span><br><span class="line"><span class="comment">            next: () =&gt; &#123;</span></span><br><span class="line"><span class="comment">                return &#123; value: this[index], done: index++ == this.length &#125;</span></span><br><span class="line"><span class="comment">            &#125;</span></span><br><span class="line"><span class="comment">        &#125;</span></span><br><span class="line"><span class="comment">    &#125; */</span></span><br><span class="line">&#125;;</span><br><span class="line"><span class="comment">// console.log(likeArray.toString())</span></span><br><span class="line"><span class="comment">// console.log(Array.from(likeArray));</span></span><br><span class="line"><span class="keyword">let</span> arr = [...likeArray]</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(arr)</span><br><span class="line"><span class="comment">// likeArray is not iterable</span></span><br></pre></td></tr></table></figure></li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* function* read() &#123;</span></span><br><span class="line"><span class="comment">    let a = yield &#x27;vue&#x27;;</span></span><br><span class="line"><span class="comment">    console.log(a, &#x27;a&#x27;)</span></span><br><span class="line"><span class="comment">    let b = yield &#x27;vite&#x27;;</span></span><br><span class="line"><span class="comment">    console.log(b, &#x27;b&#x27;)</span></span><br><span class="line"><span class="comment">    let c = yield &#x27;node&#x27;;</span></span><br><span class="line"><span class="comment">    console.log(c, &#x27;c&#x27;)</span></span><br><span class="line"><span class="comment">&#125;</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">let it = read(); // 返回一个迭代器</span></span><br><span class="line"><span class="comment">console.log(it.next()); // 每次调用next 遇到yield就停止</span></span><br><span class="line"><span class="comment">console.log(it.next(&#x27;aaa&#x27;)); // 调用next的时候可以给上一次yield的结果赋值, 如果没有上一次则传参无意义</span></span><br><span class="line"><span class="comment">console.log(it.next(&#x27;bbb&#x27;));</span></span><br><span class="line"><span class="comment">console.log(it.next(&#x27;ccc&#x27;)); */</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 每次调用的时候遇到yield就停止</span></span><br><span class="line"><span class="comment">// 下一次next传递的参数 是上一次的返回值</span></span><br><span class="line"><span class="comment">// it.throw 抛出的异常可以在代码中被捕获</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// yield产出的结果 可以等待产出的结果执行完毕后 ，在继续向下执行</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>).<span class="property">promises</span></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>)</span><br><span class="line"><span class="keyword">function</span>* <span class="title function_">read</span>(<span class="params"></span>) &#123; <span class="comment">// 这个逻辑更像同步的，但是底层我们可以变写成异步的</span></span><br><span class="line">    <span class="keyword">let</span> name = <span class="keyword">yield</span> fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&#x27;name.txt&#x27;</span>), <span class="string">&#x27;utf8&#x27;</span>);</span><br><span class="line">    <span class="keyword">let</span> age = <span class="keyword">yield</span> fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, name), <span class="string">&#x27;utf8&#x27;</span>);</span><br><span class="line">    <span class="keyword">return</span> age;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 异步串行 需要用递归来解决, 自己实现了一个迭代器 ，用来迭代generator函数</span></span><br><span class="line"><span class="comment">// const co = require(&#x27;co&#x27;)</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">co</span>(<span class="params">it</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">function</span> <span class="title function_">next</span>(<span class="params">data</span>) &#123;</span><br><span class="line">            <span class="keyword">let</span> &#123; value, done &#125; = it.<span class="title function_">next</span>(data);</span><br><span class="line">            <span class="keyword">if</span> (!done) &#123;</span><br><span class="line">                <span class="title class_">Promise</span>.<span class="title function_">resolve</span>(value).<span class="title function_">then</span>(<span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span><br><span class="line">                    <span class="title function_">next</span>(data)</span><br><span class="line">                &#125;).<span class="title function_">catch</span>(<span class="function"><span class="params">err</span> =&gt;</span> &#123;</span><br><span class="line">                    <span class="title function_">reject</span>(err);</span><br><span class="line">                &#125;)</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="title function_">resolve</span>(value);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">next</span>();</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">co</span>(<span class="title function_">read</span>()).<span class="title function_">then</span>(<span class="function"><span class="params">data</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data)</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// let it = read();</span></span><br><span class="line"><span class="comment">// let &#123; value, done &#125; = it.next();</span></span><br><span class="line"><span class="comment">// if (!done) &#123;</span></span><br><span class="line"><span class="comment">//     value.then(data =&gt; &#123;</span></span><br><span class="line"><span class="comment">//         let &#123; value, done &#125; = it.next(data)</span></span><br><span class="line"><span class="comment">//         if (!done) &#123;</span></span><br><span class="line"><span class="comment">//             value.then(data =&gt; &#123;</span></span><br><span class="line"><span class="comment">//                 let &#123; value, done &#125; = it.next(data);</span></span><br><span class="line"><span class="comment">//                 if (done) &#123;</span></span><br><span class="line"><span class="comment">//                     console.log(value)</span></span><br><span class="line"><span class="comment">//                 &#125;</span></span><br><span class="line"><span class="comment">//             &#125;).catch((e) =&gt; &#123;</span></span><br><span class="line"><span class="comment">//                 it.throw(e)</span></span><br><span class="line"><span class="comment">//             &#125;)</span></span><br><span class="line"><span class="comment">//         &#125;</span></span><br><span class="line"><span class="comment">//     &#125;).catch((e) =&gt; &#123;</span></span><br><span class="line"><span class="comment">//         it.throw(e)</span></span><br><span class="line"><span class="comment">//     &#125;)</span></span><br><span class="line"><span class="comment">// &#125;</span></span><br></pre></td></tr></table></figure>

<ul>
<li>generator-imp<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> regeneratorRuntime = &#123;</span><br><span class="line">    <span class="title function_">mark</span>(<span class="params">gen</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> gen</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">wrap</span>(<span class="params">iteratorFn</span>) &#123; <span class="comment">// 此函数iteratorFn会执行多次</span></span><br><span class="line">        <span class="keyword">const</span> _context = &#123;</span><br><span class="line">            <span class="attr">next</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">sent</span>: <span class="literal">null</span>, <span class="comment">// 下一次调用next的时候 传递的参数 会赋予给上一次的返回值</span></span><br><span class="line">            <span class="attr">done</span>: <span class="literal">false</span>,</span><br><span class="line">            <span class="title function_">stop</span>(<span class="params"></span>) &#123;</span><br><span class="line">                _context.<span class="property">done</span> = <span class="literal">true</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> &#123; <span class="comment">// it</span></span><br><span class="line">            <span class="title function_">next</span>(<span class="params">v</span>) &#123; <span class="comment">// value 就是上一次yield的返回值</span></span><br><span class="line">                _context.<span class="property">sent</span> = v; <span class="comment">// 每次调用next时会将用户的参数保存到sent上</span></span><br><span class="line">                <span class="keyword">let</span> value = <span class="title function_">iteratorFn</span>(_context);</span><br><span class="line">                <span class="keyword">return</span> &#123; value, <span class="attr">done</span>: _context.<span class="property">done</span> &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> _marked = <span class="comment">/*#__PURE__*/</span>regeneratorRuntime.<span class="title function_">mark</span>(read);</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">read</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">var</span> a, b, c;</span><br><span class="line">    <span class="keyword">return</span> regeneratorRuntime.<span class="title function_">wrap</span>(<span class="keyword">function</span> <span class="title function_">read$</span>(<span class="params">_context</span>) &#123;</span><br><span class="line">        <span class="keyword">while</span> (<span class="number">1</span>) &#123; <span class="comment">// while(true) 表示这个东西是一个状态机，根据状态的变化实现对应的逻辑， 这个逻辑会走多次</span></span><br><span class="line">            <span class="keyword">switch</span> (_context.<span class="property">prev</span> = _context.<span class="property">next</span>) &#123;</span><br><span class="line">                <span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line">                    _context.<span class="property">next</span> = <span class="number">2</span>;</span><br><span class="line">                    <span class="keyword">return</span> <span class="string">&#x27;vue&#x27;</span>;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line">                    a = _context.<span class="property">sent</span>;</span><br><span class="line">                    <span class="variable language_">console</span>.<span class="title function_">log</span>(a, <span class="string">&#x27;a&#x27;</span>);</span><br><span class="line">                    _context.<span class="property">next</span> = <span class="number">6</span>;</span><br><span class="line">                    <span class="keyword">return</span> <span class="string">&#x27;vite&#x27;</span>;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">case</span> <span class="number">6</span>:</span><br><span class="line">                    b = _context.<span class="property">sent</span>;</span><br><span class="line">                    <span class="variable language_">console</span>.<span class="title function_">log</span>(b, <span class="string">&#x27;b&#x27;</span>);</span><br><span class="line">                    _context.<span class="property">next</span> = <span class="number">10</span>;</span><br><span class="line">                    <span class="keyword">return</span> <span class="string">&#x27;node&#x27;</span>;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">case</span> <span class="number">10</span>:</span><br><span class="line">                    c = _context.<span class="property">sent</span>;</span><br><span class="line">                    <span class="variable language_">console</span>.<span class="title function_">log</span>(c, <span class="string">&#x27;c&#x27;</span>);</span><br><span class="line"></span><br><span class="line">                <span class="keyword">case</span> <span class="number">12</span>:</span><br><span class="line">                <span class="keyword">case</span> <span class="string">&quot;end&quot;</span>:</span><br><span class="line">                    <span class="keyword">return</span> _context.<span class="title function_">stop</span>();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;, _marked);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> it = <span class="title function_">read</span>()</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(it.<span class="title function_">next</span>());</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(it.<span class="title function_">next</span>(<span class="string">&#x27;aaa&#x27;</span>));</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(it.<span class="title function_">next</span>(<span class="string">&#x27;bbb&#x27;</span>));</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(it.<span class="title function_">next</span>(<span class="string">&#x27;ccc&#x27;</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">// wrap 的使用会传入编译后的函数（变成了switch case的模式将一个函数进行了拆分，根据_context.next 来决定执行对应的逻辑）</span></span><br><span class="line"><span class="comment">//  wrap函数的返回结果是迭代器迭代器要有next方法 （next函数）</span></span><br><span class="line"><span class="comment">// 每次用户会调用next方法，传入对应的值， 这个值会被保留在_context.sent上， 走下一次调用函数的时候将其取出赋值给变量</span></span><br></pre></td></tr></table></figure></li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>).<span class="property">promises</span></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>)</span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">read</span>(<span class="params"></span>) &#123; <span class="comment">// 这个逻辑更像同步的，但是底层我们可以变写成异步的</span></span><br><span class="line">    <span class="keyword">let</span> name = <span class="keyword">await</span> fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&#x27;name.txt&#x27;</span>), <span class="string">&#x27;utf8&#x27;</span>);</span><br><span class="line">    <span class="keyword">let</span> age = <span class="keyword">await</span> fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, name), <span class="string">&#x27;utf8&#x27;</span>);</span><br><span class="line">    <span class="keyword">return</span> age;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title function_">read</span>().<span class="title function_">then</span>(<span class="function"><span class="params">data</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data)</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// async - await  = generator + co</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// generator + co 是async 和await的语法糖</span></span><br><span class="line"><span class="comment">// async 函数返回的是一个promise</span></span><br><span class="line"><span class="comment">// 内部是基于generator的所以可以使用try &#123;&#125; catch语法 ，如果出现异常可以通过 promise.catch来捕获</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// generator 可以配合promise 但是需要有co 来实现流程控制</span></span><br><span class="line"><span class="comment">// promise 配合 async + await 来实现流程控制</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 异步的发展流程  回调 -》 promise -》 generator + co -》  async / await</span></span><br><span class="line"><span class="comment">// 浏览器的事件环 （js是单线程的 不考虑webworker）</span></span><br></pre></td></tr></table></figure>

<ul>
<li><p>5.async-await-imp</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&quot;use strict&quot;</span>;</span><br><span class="line"><span class="comment">// co </span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">asyncGeneratorStep</span>(<span class="params">gen, resolve, reject, _next, _throw, key, arg</span>) &#123; <span class="comment">// key -》 next /throw</span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="keyword">var</span> info = gen[key](arg);  <span class="comment">// it.next(arg)</span></span><br><span class="line">        <span class="keyword">var</span> value = info.<span class="property">value</span>;</span><br><span class="line">    &#125; <span class="keyword">catch</span> (error) &#123;</span><br><span class="line">        <span class="title function_">reject</span>(error); <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (info.<span class="property">done</span>) &#123;</span><br><span class="line">        <span class="title function_">resolve</span>(value);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="title class_">Promise</span>.<span class="title function_">resolve</span>(value).<span class="title function_">then</span>(_next, _throw);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">_asyncToGenerator</span>(<span class="params">fn</span>) &#123; <span class="comment">// fn 就是一个generator</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">var</span> self = <span class="variable language_">this</span>, args = <span class="variable language_">arguments</span>;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="keyword">function</span> (<span class="params">resolve, reject</span>) &#123;</span><br><span class="line">            <span class="keyword">var</span> gen = fn.<span class="title function_">apply</span>(self, args); <span class="comment">// 获取到iterator， 因为生成器执行完毕后返回的是迭代器</span></span><br><span class="line">            <span class="keyword">function</span> <span class="title function_">_next</span>(<span class="params">value</span>) &#123;</span><br><span class="line">                <span class="title function_">asyncGeneratorStep</span>(gen, resolve, reject, _next, _throw, <span class="string">&quot;next&quot;</span>, value);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">function</span> <span class="title function_">_throw</span>(<span class="params">err</span>) &#123;</span><br><span class="line">                <span class="title function_">asyncGeneratorStep</span>(gen, resolve, reject, _next, _throw, <span class="string">&quot;throw&quot;</span>, err);</span><br><span class="line">            &#125; <span class="title function_">_next</span>(<span class="literal">undefined</span>);</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">read</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> _read.<span class="title function_">apply</span>(<span class="variable language_">this</span>, <span class="variable language_">arguments</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">_read</span>(<span class="params"></span>) &#123;</span><br><span class="line">    _read = <span class="title function_">_asyncToGenerator</span>(regeneratorRuntime.<span class="title function_">mark</span>(<span class="keyword">function</span> <span class="title function_">_callee</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">var</span> name, age;</span><br><span class="line">        <span class="keyword">return</span> regeneratorRuntime.<span class="title function_">wrap</span>(<span class="keyword">function</span> <span class="title function_">_callee$</span>(<span class="params">_context</span>) &#123;</span><br><span class="line">            <span class="keyword">while</span> (<span class="number">1</span>) &#123;</span><br><span class="line">                <span class="keyword">switch</span> (_context.<span class="property">prev</span> = _context.<span class="property">next</span>) &#123;</span><br><span class="line">                    <span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line">                        _context.<span class="property">next</span> = <span class="number">2</span>;</span><br><span class="line">                        <span class="keyword">return</span> fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&#x27;name.txt&#x27;</span>), <span class="string">&#x27;utf8&#x27;</span>);</span><br><span class="line"></span><br><span class="line">                    <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line">                        name = _context.<span class="property">sent</span>;</span><br><span class="line">                        _context.<span class="property">next</span> = <span class="number">5</span>;</span><br><span class="line">                        <span class="keyword">return</span> fs.<span class="title function_">readFile</span>(path.<span class="title function_">resolve</span>(__dirname, name), <span class="string">&#x27;utf8&#x27;</span>);</span><br><span class="line"></span><br><span class="line">                    <span class="keyword">case</span> <span class="number">5</span>:</span><br><span class="line">                        age = _context.<span class="property">sent</span>;</span><br><span class="line">                        <span class="keyword">return</span> _context.<span class="title function_">abrupt</span>(<span class="string">&quot;return&quot;</span>, age);</span><br><span class="line"></span><br><span class="line">                    <span class="keyword">case</span> <span class="number">7</span>:</span><br><span class="line">                    <span class="keyword">case</span> <span class="string">&quot;end&quot;</span>:</span><br><span class="line">                        <span class="keyword">return</span> _context.<span class="title function_">stop</span>();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;, _callee);</span><br><span class="line">    &#125;));</span><br><span class="line">    <span class="keyword">return</span> _read.<span class="title function_">apply</span>(<span class="variable language_">this</span>, <span class="variable language_">arguments</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//1) async 方法会变成一个promise</span></span><br><span class="line"><span class="comment">//2) </span></span><br></pre></td></tr></table></figure>
</li>
<li><p>eventLoop<br>基本的概念  进程和线程之间的关系<br>计算机分配任务是以进程来分配的 ， 进程中包含着线程</p>
</li>
</ul>
<p>浏览器是一个进程  而且是一个多进程模型 （多进程的好处就是其中一个进程挂掉了，不会影响其他进程）<br>一个tab就是一个独立的进程<br>浏览器默认要有一个主进程，来调度其他进程  （进程间的通信）<br>网络进程  发送http请求等<br>插件也有独立的进程<br>gpu绘图进程<br>一个tab就是一个独立的进程 (渲染进程)</p>
<p>渲染进程 (线程)<br>ui 渲染线程  负责页面渲染，布局，绘制<br>js 引擎线程  执行js代码的</p>
<p>互斥的：js可以操作dom ，渲染需要dom  如果正在渲染页面时，渲染到一半了如果js要求把dom删除掉？<br>js也是单线程的， 由于如果js是多线程操作dom的会导致 一个线程说我要添加一个节点， 另一个说我要删除节点？</p>
<p>js也是单线程的 指代的是主线程 （默认代码从上到下依次执行）<br>定时器， 发请求， 用户事件 （在主线程执行的时候 还会创建一些独立的线程）</p>
<p>异步 ： 为异步任务划分优先级<br>宏任务和微任务执行时机不一样<br>宏任务 macro-task： 写的script脚本， ui渲染，定时器(setTimeout)， 发请求， 用户事件，messageChannel, setImmediate(ie下有，比setTimeout性能好)</p>
<p>微任务 micro-task： Promise.then(语言本身提供的)， queueMicrotashk  MutationObserver （异步监控dom的变化）</p>
<p>requestFrameAnimation requestAdleCallback (发生在渲染里的， 就是个回调函数， 这个东西不应该分到宏任务和微任务中)</p>
<p>js 执行的顺序怎么定义呢？ 先执行完当前同步代码，再去执行异步代码。 有一个单独的线程来扫描异步任务 事件触发线程EventLoop</p>
<p>代码执行的过程的时候 会产生微任务和宏任务<br>当发生的宏任务时间到达的时候会被发入到宏任务队列中 (放入是回调) 宏任务只有一个队列<br>微任务是立刻放到队列中 （每次执行宏任务的时候会产生一个微任务队列）</p>
<p>当前宏任务执行完毕后，会清空本轮产生的微任务, 如果执行微任务的时候又产生了微任务，会放到当前微任务的尾部<br>看一眼要不要渲染页面？ 要渲染就渲染（requestFrameAnimation requestAdleCallback） 刷新频率 16.6ms</p>
<p>再去扫描宏任务队列，如果有则取出第一个宏任务 ， 再去执行</p>
<p>每次微任务是执行一批 ， 宏任务是执行一个</p>
<p><img src="/bailment-blog/images/down.png"></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 打印的结果</span></span><br><span class="line"><span class="comment">// 页面渲染的颜色 会不会从 red -&gt; yellow</span></span><br><span class="line"><span class="variable language_">document</span>.<span class="property">body</span>.<span class="property">style</span>.<span class="property">background</span> = <span class="string">&#x27;red&#x27;</span>;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">1</span>)</span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="function">()=&gt;</span>&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">2</span>)</span><br><span class="line">    <span class="variable language_">document</span>.<span class="property">body</span>.<span class="property">style</span>.<span class="property">background</span> = <span class="string">&#x27;yellow&#x27;</span>;</span><br><span class="line">&#125;)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">3</span>);</span><br><span class="line"><span class="comment">// 渲染逻辑可能是在宏任务之后</span></span><br><span class="line"><span class="comment">// 1 3 2  yellow</span></span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="title class_">Promise</span>.<span class="title function_">resolve</span>().<span class="title function_">then</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Promise1&#x27;</span>)</span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;setTimeout2&#x27;</span>)</span><br><span class="line">        &#125;, <span class="number">0</span>);</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;setTimeout1&#x27;</span>);</span><br><span class="line">        <span class="title class_">Promise</span>.<span class="title function_">resolve</span>().<span class="title function_">then</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Promise2&#x27;</span>)</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 微任务队列 ： [Promise2]</span></span><br><span class="line">    <span class="comment">// 宏任务队列: [setTimeout1,setTimeout2]</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// Promise1</span></span><br><span class="line">    <span class="comment">// setTimeout1</span></span><br><span class="line">    <span class="comment">// Promise2</span></span><br><span class="line">    <span class="comment">// setTimeout2</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">button.<span class="title function_">addEventListener</span>(<span class="string">&#x27;click&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;listener1&#x27;</span>);</span><br><span class="line">    <span class="title class_">Promise</span>.<span class="title function_">resolve</span>().<span class="title function_">then</span>(<span class="function">() =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;micro task1&#x27;</span>))</span><br><span class="line">&#125;)</span><br><span class="line">button.<span class="title function_">addEventListener</span>(<span class="string">&#x27;click&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;listener2&#x27;</span>);</span><br><span class="line">    <span class="title class_">Promise</span>.<span class="title function_">resolve</span>().<span class="title function_">then</span>(<span class="function">() =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;micro task2&#x27;</span>))</span><br><span class="line">&#125;)</span><br><span class="line">button.<span class="title function_">click</span>(); <span class="comment">// click1() click2()</span></span><br><span class="line"><span class="comment">// 默认 21 行 和 点击的时候的区别是什么？</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">1</span>);</span><br><span class="line">    <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">async</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">2</span>);</span><br><span class="line">        <span class="keyword">await</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">3</span>); <span class="comment">// Promise.resolve(console.log(3)).then(()=&gt;&#123; console.log(4)&#125;)</span></span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">4</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">5</span>);</span><br><span class="line">    &#125;, <span class="number">0</span>);</span><br><span class="line">    <span class="keyword">const</span> promise = <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">6</span>);</span><br><span class="line">        <span class="title function_">resolve</span>(<span class="number">7</span>)</span><br><span class="line">    &#125;)</span><br><span class="line">    promise.<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(res)</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="title function_">async</span>();</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">8</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 微任务队列  [7,4]</span></span><br><span class="line">    <span class="comment">// 1   6     2     3      8    7     4       5</span></span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://gitee.com/wieldy/bailment-blog/2022/03/29/async/" data-id="cljmgj1ev000bzc9jflgged0p" data-title="Async" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-buffer" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/bailment-blog/2022/03/29/buffer/" class="article-date">
  <time class="dt-published" datetime="2022-03-29T14:12:00.000Z" itemprop="datePublished">2022-03-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/bailment-blog/2022/03/29/buffer/">buffer</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <ul>
<li><p>1.npm</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 第三方模块 : 别人写好的模块 我们需要手动安装 ， 安装后用法同核心模块</span></span><br><span class="line"><span class="comment">// 引用的时候 不需要加相对路径或者绝对路径</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// npm node package manager 包管理工具  当我们安装node后可以直接使用</span></span><br><span class="line"><span class="comment">// 环境变量npm node 安装到环境变量中的都可以直接使用 （只要需要全局使用都需要配置到path中）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// node里面有3个n   npm   nrm (管理从哪里去下载的)   nvm(在window下 nvm-win) 切换node版本</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// npm install nrm -g  (也可以在项目下创建.npmrc的文件单独对某个项目去配置)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// npm install nrm -g (安装一个全局的模块，就是可以在命令中直接使用)</span></span><br><span class="line"><span class="comment">// 我们安装的全局包 都会被安装到npm的全局目录下。这样都可以直接使用 （npm目录被放置到了path下）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 全局模块 （只能在命令行中用，不能在项目中使用）</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">module</span>.<span class="property">paths</span>); <span class="comment">// C:\Users\test1\AppData\Roaming\npm</span></span><br><span class="line"><span class="comment">// 常见的就是一些编译操作 都是全局模块、脚手架 也都是全局的  （vue/cli,  cra）</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 1） 我们需要创建可执行文件 添加执行环境 #! /usr/bin/env node</span></span><br><span class="line"><span class="comment">// 2) 配置package.json中的bin参数</span></span><br><span class="line"><span class="comment">// 3) npm link 创建软链到全局下 （为了测试）  或者直接发布 通过npm install -g来进行安装</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 作用域 （@xxx/north  @qqq/north）、 全局的 （会重名）   @bable/core @babel/cli @babel/runtime-core</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// C: \Users\test1\AppData\Roaming\npm\my-npm-package -&gt; C: \Users\test1\AppData\Roaming\npm\node_modules\my-npm-package\bin\www</span></span><br><span class="line"><span class="comment">// C: \Users\test1\AppData\Roaming\npm\node_modules\my-npm-package -&gt; C: \Users\test1\Desktop\promise-1\5.buffer</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 4) 发布的时候 每次版本都需要更新semver 规范 major.minor.patch  (根据测试版本发包的)  beta alpha release</span></span><br><span class="line"><span class="comment">// 5) 发布包 npm publish (如果是向npm官方发布 需要切换到npm源上  登录账号)  --scope</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// npm version 版本号 （major | minor | patch）</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 第三方模块</span></span><br><span class="line"><span class="comment">// 在项目中安装模块 （这个项目需要用的模块）</span></span><br><span class="line"><span class="comment">// 项目依赖  开发、生产都需要的包 --save 新版本默认不要增加了  vue</span></span><br><span class="line"><span class="comment">// 开发依赖  webpack rollup... --save-dev 开发的时候需要 上线的时候不需要</span></span><br><span class="line"><span class="comment">// 同等依赖  我安装一个包 需要告诉你用一个其他包  bootstrap. jquery  警告</span></span><br><span class="line"><span class="comment">// 可选依赖  你安装不装</span></span><br><span class="line"><span class="comment">// 捆绑依赖  当使用npm pack的时候 会将模块对应的压缩进去</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// npm中package.lock.json 作用就是锁定版本 ^3.6.0 只能比3大的 比4小的 如果有一天包升级到了3.7 (npm install )</span></span><br><span class="line"><span class="comment">// lock文件就是记录好确定的版本 （防止版本安装出问题）  ~2.3.0 只要比2.3大的 比 2.4小的即可  &gt;=  &lt;= &lt; &gt;</span></span><br><span class="line"><span class="comment">// 我只想安装生产依赖 不安装开发依赖  npm install --prodction</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 只要是一个包 必须有package.json   npm init -y</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// npm有个优化处理 会把包拍平 但是版本不一致不会被抽离出来，而是每个包都是自己的</span></span><br><span class="line"><span class="comment">// 服务端代码不用打包。 （后端编译 其实ts-》 js）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// main 字段是给 require() 用的</span></span><br><span class="line"><span class="comment">// module 字段是给 import</span></span><br><span class="line"><span class="comment">// bin 给执行脚本的时候用的</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 幽灵依赖：  我的项目中用了 a包 -》 b包   b包也会被安装到node_modules下  require(&quot;b&quot;) 有一天a删除了，b就没有了，项目中用了b就出问题了</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 执行脚本</span></span><br><span class="line"><span class="comment">// mime 就是给一个文件名就可以来看下这个文件类型  (例如webpack 我们希望把它安装到全局下么？)</span></span><br><span class="line"><span class="comment">// a用了webpack -》 4.5本地</span></span><br><span class="line"><span class="comment">// b用了webpack -》 5 本地</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 最终将webpack安装到项目下，使用项目中webpack来打包</span></span><br><span class="line"><span class="comment">// 默认通过npm run xxx 的时候 会将当前项目下node_modules/.bin这个目录放到全局的path, 执行后就删除了</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// npx 也可以执行 .bin 目录下的文件 （核心也是将当前的node_modules/.bin）放到环境中，如果没有这个模块会下载， 如果有直接使用</span></span><br><span class="line"><span class="comment">// 如果下载完后  命令执行结束了 会被删除掉 , 初始化项目配置文件可能用到npx</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
</li>
<li><p>2.buffer</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1) node 中的模块实现原理 commonjs </span></span><br><span class="line"><span class="comment">// 2) 核心模块的用法  npm第三方模块用法</span></span><br><span class="line"><span class="comment">// 3) global属性 process node EventLoop</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 我们在node中要操作文件 （文件读写 内存 二进制）  描述内存的 buffer （默认都是二进制数据）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 转化规则 一个字节由8个bit位组成 （0/1）  二进制逢二进一  十进制是逢10进一  16进制 逢十进1</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 1111111   -&gt; 255   (一个字节最大是255)</span></span><br><span class="line"><span class="comment">// 255 -&gt; 16进制  -&gt; ff</span></span><br><span class="line"><span class="comment">// 255 -&gt; 8进制？ -&gt; 377</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 二进制转化成10进制 可以采用 当前位的值 * 进制^（所在位-1） 累加</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// NODE中的buffer 是以16进制来处理的 （只是因为16进制比较短）  进制只是表现， 一个数可以表现成不同的进制</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 0b开头的是2进制 </span></span><br><span class="line"><span class="comment">// 0o开头的是8进制</span></span><br><span class="line"><span class="comment">// 0x开头的是16进制</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">100.</span>.<span class="title function_">toString</span>(<span class="number">16</span>)); <span class="comment">// 64  字符串</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="built_in">parseInt</span>(<span class="string">&#x27;1100100&#x27;</span>, <span class="number">2</span>)); <span class="comment">// 可以将任何的进制转化成10进制</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="built_in">parseInt</span>(<span class="string">&#x27;ff&#x27;</span>, <span class="number">16</span>)); <span class="comment">// 将进制转化成10进制 </span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 小数怎么转化成2进制   0.1 + 0.2 为啥不等于0.3</span></span><br><span class="line"><span class="comment">// 小数的转化规则 乘二取证法</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 0.1  =&gt; 0.2 -&gt;  0</span></span><br><span class="line"><span class="comment">// 0.2  =&gt; 0.4 -&gt;  0</span></span><br><span class="line"><span class="comment">// 0.4  =&gt; 0.8 -&gt;  0</span></span><br><span class="line"><span class="comment">// 0.8  =&gt; 1.6 -&gt;  1</span></span><br><span class="line"><span class="comment">// 0.6  =&gt; 1.2 =&gt;  1</span></span><br><span class="line"><span class="comment">// 0.2 -&gt; ......   </span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">0.1</span>.<span class="title function_">toString</span>(<span class="number">2</span>)); <span class="comment">// 不能用有限的空间来描述无限的值 （精确 比以前的值大）</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">0.2</span>.<span class="title function_">toString</span>(<span class="number">2</span>));  <span class="comment">// 得到的肯定是一个近似值 -》 得出了一个偏大的值</span></span><br><span class="line"><span class="comment">// 0.2 + 0.2 近似值</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 那如何解决这个问题呢？ </span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> sum = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="number">8</span>; i++) &#123;</span><br><span class="line">    sum += <span class="number">1</span> * <span class="number">2</span> ** i</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(sum)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">2</span> ** <span class="number">8</span> - <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// base64转化  编码任何东西 基于二进制的 （方便传输）  好处就是base64 可以替换任何的url地址 （减少请求）</span></span><br><span class="line"><span class="comment">// 编码： 不叫加密  (编码可以反编码， 加密需要有对应的秘钥解密， 编码是一套开放的方案)</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 汉字 node中统一默认只支持utf8格式 一个汉字由3个字节组成  3 * 8 = 24位  </span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Buffer</span>.<span class="title function_">from</span>(<span class="string">&#x27;珠&#x27;</span>)); <span class="comment">// e7 8f a0</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>((<span class="number">0xe7</span>).<span class="title function_">toString</span>(<span class="number">2</span>))</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>((<span class="number">0x8f</span>).<span class="title function_">toString</span>(<span class="number">2</span>))</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>((<span class="number">0xa0</span>).<span class="title function_">toString</span>(<span class="number">2</span>))</span><br><span class="line"><span class="comment">// 将汉字转化成base64格式  特点就是每一个字节不得超过64 (由64个字符组合而成)</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 11100111  10001111  10100000 -&gt; 24位   3* 8 =&gt;   4*6</span></span><br><span class="line"><span class="comment">// 111001  111000  111110   100000</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="built_in">parseInt</span>(<span class="string">&#x27;111001&#x27;</span>, <span class="number">2</span>))</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="built_in">parseInt</span>(<span class="string">&#x27;111000&#x27;</span>, <span class="number">2</span>))</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="built_in">parseInt</span>(<span class="string">&#x27;111110&#x27;</span>, <span class="number">2</span>))</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="built_in">parseInt</span>(<span class="string">&#x27;100000&#x27;</span>, <span class="number">2</span>))</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> code = <span class="string">&#x27;ABCDEFGHIJKLMNOPQRSTUVWXYZ&#x27;</span></span><br><span class="line">code += code.<span class="title function_">toLowerCase</span>();</span><br><span class="line">code += <span class="string">&#x27;0123456789&#x27;</span></span><br><span class="line">code += <span class="string">&#x27;+/&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 57 56 62 32</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(code[<span class="number">57</span>] + code[<span class="number">56</span>] + code[<span class="number">62</span>] + code[<span class="number">32</span>]); <span class="comment">// 54+g  4个字节  比以前大了1/3</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// base64 编译出来的结果会比以前大 （不是所有的东西都要转化成base64）</span></span><br><span class="line"><span class="comment">// base32 咋实现的？  00011111 </span></span><br></pre></td></tr></table></figure></li>
</ul>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//package.json</span></span><br><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;@pamzer156/xxx-npm-package&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;public&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="string">&quot;2.1.1&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;description&quot;</span><span class="punctuation">:</span> <span class="string">&quot;&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;main&quot;</span><span class="punctuation">:</span> <span class="string">&quot;1.npm.js&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;bin&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;n&quot;</span><span class="punctuation">:</span> <span class="string">&quot;./bin/www&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;my-npm-package&quot;</span><span class="punctuation">:</span> <span class="string">&quot;./bin/www&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;scripts&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;mime&quot;</span><span class="punctuation">:</span> <span class="string">&quot;mime&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;keywords&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;author&quot;</span><span class="punctuation">:</span> <span class="string">&quot;&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;license&quot;</span><span class="punctuation">:</span> <span class="string">&quot;MIT&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;dependencies&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;bootstrap&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^3.0.0&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;mime&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^3.0.0&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;peerDependencies&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;jquery&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^2.0.0&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;optionalDependencies&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span><span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;bundledDependencies&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="string">&quot;bootstrap&quot;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;devDependencies&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;rollup&quot;</span><span class="punctuation">:</span> <span class="string">&quot;^2.72.0&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://gitee.com/wieldy/bailment-blog/2022/03/29/buffer/" data-id="cljmgj1ev000czc9jadmi4e06" data-title="buffer" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-cookie-session-jwt" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/bailment-blog/2022/03/29/cookie-session-jwt/" class="article-date">
  <time class="dt-published" datetime="2022-03-29T14:12:00.000Z" itemprop="datePublished">2022-03-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/bailment-blog/2022/03/29/cookie-session-jwt/">cookie-session-jwt</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <ul>
<li><p>http</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//cookie就是服务端设置的一个header，cookie也可以前端来设置</span></span><br><span class="line"><span class="keyword">const</span> http = <span class="built_in">require</span>(<span class="string">&#x27;http&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> crypto = <span class="built_in">require</span>(<span class="string">&#x27;crypto&#x27;</span>);</span><br><span class="line"><span class="comment">// 摘要算法:  摘要算法不是加密算法 ： 加密的能解密。 摘要算法不可逆</span></span><br><span class="line"><span class="comment">// md5  1) 不可逆 2）相同的内容摘要的结果相同 3） 无论多大的内容摘要的结果长度都是一致的  4） 如果内容不一样摘要的结果会有很大变化</span></span><br><span class="line"><span class="comment">// console.log(crypto.createHash(&#x27;md5&#x27;).update(&#x27;123&#x27;).digest(&#x27;base64&#x27;))</span></span><br><span class="line"><span class="comment">// console.log(crypto.createHash(&#x27;md5&#x27;).update(&#x27;1234&#x27;).digest(&#x27;base64&#x27;))</span></span><br><span class="line"><span class="comment">// 加盐算法： 用户提供一个秘钥， 这个秘钥只有你知道，别人不知道 ， 通过唯一的秘钥进行摘要</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 盐值 可以根据不同的盐值进行计算， 只要盐值不同就不会摘要出相同的内容  2048字节</span></span><br><span class="line"><span class="comment">// console.log(crypto.createHmac(&#x27;sha1&#x27;, &#x27;xxx&#x27;).update(&#x27;123&#x27;).digest(&#x27;base64&#x27;));</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> secret = <span class="string">&#x27;zfjg&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">sign</span> = (<span class="params">value</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> (crypto.<span class="title function_">createHmac</span>(<span class="string">&#x27;sha1&#x27;</span>, secret).<span class="title function_">update</span>(value).<span class="title function_">digest</span>(<span class="string">&#x27;base64&#x27;</span>)).<span class="title function_">replace</span>(<span class="regexp">/\+/g</span>, <span class="string">&#x27;-&#x27;</span>).<span class="title function_">replace</span>(<span class="regexp">/\//g</span>, <span class="string">&#x27;_&#x27;</span>).<span class="title function_">replace</span>(<span class="regexp">/=/g</span>, <span class="string">&#x27;&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// age=1.3.签名  express</span></span><br><span class="line"><span class="comment">// age.signed = &#x27;值是多少&#x27;  koa</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> server = http.<span class="title function_">createServer</span>(<span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// name,value cookie的key和value</span></span><br><span class="line">    <span class="comment">// path  可以通过路径来区分哪个路径下可以访问cookie ， 限制访问的范围 </span></span><br><span class="line">    <span class="comment">// domain 域名 限制哪个域名可以访问cookie  （为了共享cookie的）  限制两个子域共享cookie </span></span><br><span class="line">    <span class="comment">// max-age cookie的有效期 cookie的存活时间</span></span><br><span class="line">    <span class="comment">// httpOnly  服务端设置的cookie 前端无法通过代码获取到，为了保证信息安全 </span></span><br><span class="line">    <span class="keyword">let</span> arr = [];</span><br><span class="line">    res.<span class="property">setCookie</span> = <span class="keyword">function</span> (<span class="params">name, value, options = &#123;&#125;</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> optionsArr = [];</span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">path</span>) &#123;</span><br><span class="line">            optionsArr.<span class="title function_">push</span>(<span class="string">`path=<span class="subst">$&#123;options.path&#125;</span>`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">domain</span>) &#123;</span><br><span class="line">            optionsArr.<span class="title function_">push</span>(<span class="string">`domain=<span class="subst">$&#123;options.domain&#125;</span>`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">maxAge</span>) &#123;</span><br><span class="line">            optionsArr.<span class="title function_">push</span>(<span class="string">`max-age=<span class="subst">$&#123;options.maxAge&#125;</span>`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">httpOnly</span>) &#123;</span><br><span class="line">            optionsArr.<span class="title function_">push</span>(<span class="string">`httpOnly=<span class="subst">$&#123;options.httpOnly&#125;</span>`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">signed</span>) &#123;</span><br><span class="line">            <span class="keyword">let</span> s = <span class="title function_">sign</span>(<span class="string">`<span class="subst">$&#123;name&#125;</span>=<span class="subst">$&#123;value&#125;</span>`</span>);</span><br><span class="line">            arr.<span class="title function_">push</span>(<span class="string">`<span class="subst">$&#123;name&#125;</span>.sign=<span class="subst">$&#123;s&#125;</span>`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        arr.<span class="title function_">push</span>(<span class="string">`<span class="subst">$&#123;name&#125;</span> = <span class="subst">$&#123;value&#125;</span>; <span class="subst">$&#123;optionsArr.join(<span class="string">&#x27;; &#x27;</span>)&#125;</span> `</span>)</span><br><span class="line">        <span class="comment">// res.setHeader(&#x27;Set-Cookie&#x27;, [&#x27;name=zf; domain=.zf.cn&#x27;, &#x27;age=13&#x27;, &#x27;name=zf; domain=a.zf.cn&#x27;]);</span></span><br><span class="line">        res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Set-Cookie&#x27;</span>, arr);</span><br><span class="line">    &#125;</span><br><span class="line">    res.<span class="property">getCookie</span> = <span class="keyword">function</span> (<span class="params">name, options = &#123;&#125;</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> cookie = req.<span class="property">headers</span>[<span class="string">&#x27;cookie&#x27;</span>];</span><br><span class="line">        <span class="comment">// a=b&amp;c=d   a=b; c=d</span></span><br><span class="line">        <span class="keyword">let</span> cookieObj = <span class="built_in">require</span>(<span class="string">&#x27;querystring&#x27;</span>).<span class="title function_">parse</span>(cookie, <span class="string">&#x27;; &#x27;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">signed</span>) &#123; <span class="comment">// 要校验签名</span></span><br><span class="line">            <span class="comment">// 如果用户携带的签名，和用你带过来的key=value再次算出来的一样说明内容没有篡改</span></span><br><span class="line">            <span class="keyword">if</span> (cookieObj[name + <span class="string">&#x27;.sign&#x27;</span>] === <span class="title function_">sign</span>(<span class="string">`<span class="subst">$&#123;name&#125;</span>=<span class="subst">$&#123;cookieObj[name]&#125;</span>`</span>)) &#123;</span><br><span class="line">                <span class="keyword">return</span> cookieObj[name]</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="string">&#x27;update&#x27;</span>; <span class="comment">// 篡改了</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> cookieObj[name] || <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 防止用户或者第三方篡改内容   签名</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (req.<span class="property">url</span> === <span class="string">&#x27;/write&#x27;</span>) &#123; <span class="comment">// 访问write就写入cookie</span></span><br><span class="line">        <span class="comment">// 分隔符是分号空格  querystring  a=b&amp;c=d</span></span><br><span class="line">        <span class="comment">//  res.setCookie(&#x27;name&#x27;, &#x27;zf&#x27;); // [path:&#x27;/&#x27;]</span></span><br><span class="line">        res.<span class="title function_">setCookie</span>(<span class="string">&#x27;age&#x27;</span>, <span class="string">&#x27;20&#x27;</span>, &#123; <span class="attr">signed</span>: <span class="literal">true</span> &#125;); <span class="comment">// 应该增添签名逻辑，用于服务端校验使用</span></span><br><span class="line">        <span class="keyword">return</span> res.<span class="title function_">end</span>(<span class="string">&#x27;write ok&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// if (req.url === &#x27;/write/read&#x27;) &#123;</span></span><br><span class="line">    <span class="comment">//     let cookie = req.headers[&#x27;cookie&#x27;] || &#x27;empty&#x27;;</span></span><br><span class="line">    <span class="comment">//     return res.end(cookie)</span></span><br><span class="line">    <span class="comment">// &#125;</span></span><br><span class="line">    <span class="keyword">if</span> (req.<span class="property">url</span> === <span class="string">&#x27;/read&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> res.<span class="title function_">end</span>(res.<span class="title function_">getCookie</span>(<span class="string">&#x27;age&#x27;</span>, &#123; <span class="attr">signed</span>: <span class="literal">true</span> &#125;));</span><br><span class="line">    &#125;</span><br><span class="line">    res.<span class="title function_">end</span>(<span class="string">&#x27;Not Found&#x27;</span>)</span><br><span class="line">&#125;)</span><br><span class="line">server.<span class="title function_">listen</span>(<span class="number">3000</span>);</span><br></pre></td></tr></table></figure>
</li>
<li><p>session</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> http = <span class="built_in">require</span>(<span class="string">&#x27;http&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> crypto = <span class="built_in">require</span>(<span class="string">&#x27;crypto&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> uuid = <span class="built_in">require</span>(<span class="string">&#x27;uuid&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> secret = <span class="string">&#x27;zfjg&#x27;</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">sign</span> = (<span class="params">value</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> (crypto.<span class="title function_">createHmac</span>(<span class="string">&#x27;sha1&#x27;</span>, secret).<span class="title function_">update</span>(value).<span class="title function_">digest</span>(<span class="string">&#x27;base64&#x27;</span>)).<span class="title function_">replace</span>(<span class="regexp">/\+/g</span>, <span class="string">&#x27;-&#x27;</span>).<span class="title function_">replace</span>(<span class="regexp">/\//g</span>, <span class="string">&#x27;_&#x27;</span>).<span class="title function_">replace</span>(<span class="regexp">/=/g</span>, <span class="string">&#x27;&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> session = &#123;&#125;; <span class="comment">// session就是一个内存空间, 需要持久化，持久化可能会丢失  session没法跨域</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 谁发的卡</span></span><br><span class="line"><span class="keyword">const</span> cardName = <span class="string">&#x27;connect.sid&#x27;</span>; <span class="comment">// 卡名：卡号</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> server = http.<span class="title function_">createServer</span>(<span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">let</span> arr = [];</span><br><span class="line">    res.<span class="property">setCookie</span> = <span class="keyword">function</span> (<span class="params">name, value, options = &#123;&#125;</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> optionsArr = [];</span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">path</span>) &#123;</span><br><span class="line">            optionsArr.<span class="title function_">push</span>(<span class="string">`path=<span class="subst">$&#123;options.path&#125;</span>`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">domain</span>) &#123;</span><br><span class="line">            optionsArr.<span class="title function_">push</span>(<span class="string">`domain=<span class="subst">$&#123;options.domain&#125;</span>`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">maxAge</span>) &#123;</span><br><span class="line">            optionsArr.<span class="title function_">push</span>(<span class="string">`max-age=<span class="subst">$&#123;options.maxAge&#125;</span>`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">httpOnly</span>) &#123;</span><br><span class="line">            optionsArr.<span class="title function_">push</span>(<span class="string">`httpOnly=<span class="subst">$&#123;options.httpOnly&#125;</span>`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">signed</span>) &#123;</span><br><span class="line">            <span class="keyword">let</span> s = <span class="title function_">sign</span>(<span class="string">`<span class="subst">$&#123;name&#125;</span>=<span class="subst">$&#123;value&#125;</span>`</span>);</span><br><span class="line">            arr.<span class="title function_">push</span>(<span class="string">`<span class="subst">$&#123;name&#125;</span>.sign=<span class="subst">$&#123;s&#125;</span>`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        arr.<span class="title function_">push</span>(<span class="string">`<span class="subst">$&#123;name&#125;</span> = <span class="subst">$&#123;value&#125;</span>; <span class="subst">$&#123;optionsArr.join(<span class="string">&#x27;; &#x27;</span>)&#125;</span> `</span>)</span><br><span class="line">        <span class="comment">// res.setHeader(&#x27;Set-Cookie&#x27;, [&#x27;name=zf; domain=.zf.cn&#x27;, &#x27;age=13&#x27;, &#x27;name=zf; domain=a.zf.cn&#x27;]);</span></span><br><span class="line">        res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Set-Cookie&#x27;</span>, arr);</span><br><span class="line">    &#125;</span><br><span class="line">    res.<span class="property">getCookie</span> = <span class="keyword">function</span> (<span class="params">name, options = &#123;&#125;</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> cookie = req.<span class="property">headers</span>[<span class="string">&#x27;cookie&#x27;</span>];</span><br><span class="line">        <span class="comment">// a=b&amp;c=d   a=b; c=d</span></span><br><span class="line">        <span class="keyword">let</span> cookieObj = <span class="built_in">require</span>(<span class="string">&#x27;querystring&#x27;</span>).<span class="title function_">parse</span>(cookie, <span class="string">&#x27;; &#x27;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (options.<span class="property">signed</span>) &#123; <span class="comment">// 要校验签名</span></span><br><span class="line">            <span class="comment">// 如果用户携带的签名，和用你带过来的key=value再次算出来的一样说明内容没有篡改</span></span><br><span class="line">            <span class="keyword">if</span> (cookieObj[name + <span class="string">&#x27;.sign&#x27;</span>] === <span class="title function_">sign</span>(<span class="string">`<span class="subst">$&#123;name&#125;</span>=<span class="subst">$&#123;cookieObj[name]&#125;</span>`</span>)) &#123;</span><br><span class="line">                <span class="keyword">return</span> cookieObj[name]</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="string">&#x27;update&#x27;</span>; <span class="comment">// 篡改了</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> cookieObj[name] || <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (req.<span class="property">url</span> === <span class="string">&#x27;/visit&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> cardNum = res.<span class="title function_">getCookie</span>(cardName)</span><br><span class="line">        <span class="keyword">if</span> (cardNum &amp;&amp; session[cardNum]) &#123;</span><br><span class="line">            <span class="comment">// 不是第一次来的</span></span><br><span class="line">            session[cardNum].<span class="property">money</span> -= <span class="number">10</span>;</span><br><span class="line">            res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Content-Type&#x27;</span>, <span class="string">&#x27;text/plain;charset=utf-8&#x27;</span>)</span><br><span class="line">            res.<span class="title function_">end</span>(<span class="string">&#x27;亲~ 欢迎,账户里有&#x27;</span> + session[cardNum].<span class="property">money</span> + <span class="string">&#x27;块&#x27;</span>)</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">let</span> cardNum = uuid.<span class="title function_">v4</span>()<span class="comment">// uuid</span></span><br><span class="line">            session[cardNum] = &#123; <span class="attr">money</span>: <span class="number">200</span> &#125;; <span class="comment">// 重要的信息存放到了服务器上</span></span><br><span class="line">            res.<span class="title function_">setCookie</span>(cardName, cardNum, &#123; <span class="attr">signed</span>: <span class="literal">true</span>, <span class="attr">httpOnly</span>: <span class="literal">true</span>, <span class="attr">maxAge</span>: <span class="number">5</span> &#125;);</span><br><span class="line">            res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Content-Type&#x27;</span>, <span class="string">&#x27;text/plain;charset=utf-8&#x27;</span>)</span><br><span class="line">            res.<span class="title function_">end</span>(<span class="string">&#x27;亲~ 欢迎您第一次来,账户里有200块&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;)</span><br><span class="line">server.<span class="title function_">listen</span>(<span class="number">3000</span>);</span><br></pre></td></tr></table></figure>
</li>
<li><p>jwt</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// jwt json web token  服务端不需要记录用户的登录状态， 只用存秘钥即可。 盐值  原理和cookie签名一致</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> http = <span class="built_in">require</span>(<span class="string">&#x27;http&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> jwt = <span class="built_in">require</span>(<span class="string">&#x27;jwt-simple&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> crypto = <span class="built_in">require</span>(<span class="string">&#x27;crypto&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> secret = <span class="string">&#x27;zfjg&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// token中放入用户的唯一标识  用户的卡号 payload   &#123;_id: &#x27;zf&#x27;&#125; </span></span><br><span class="line"><span class="comment">// 每次携带token访问服务器， 我就可以取出你的卡号&#x27;zf&#x27; 可以查询数据库，拉取用户信息</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// token 可以放到header 服务端可以允许header</span></span><br><span class="line"><span class="comment">// token 可以放到url， 例如现在的场景  config.headers.authorization  = &#x27;token&#x27;</span></span><br><span class="line"><span class="comment">// 还可放到请求体中携带过去  </span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 跨域靠服务端就能解决  nginx做转发 ， cookie默认不支持跨域</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 解决了跨域问题 同时解决了session共享问题 （jwt 只要服务端token不丢，就可以）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 前后端不分离的项目一般用session  前后端分离的token</span></span><br><span class="line"><span class="keyword">const</span> jw = &#123;</span><br><span class="line">    <span class="title function_">sign</span>(<span class="params">value, secret</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (crypto.<span class="title function_">createHmac</span>(<span class="string">&#x27;sha256&#x27;</span>, secret).<span class="title function_">update</span>(value).<span class="title function_">digest</span>(<span class="string">&#x27;base64&#x27;</span>))</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">toBase64URL</span>(<span class="params">value</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> value.<span class="title function_">replace</span>(<span class="regexp">/\+/g</span>, <span class="string">&#x27;-&#x27;</span>).<span class="title function_">replace</span>(<span class="regexp">/\//g</span>, <span class="string">&#x27;_&#x27;</span>).<span class="title function_">replace</span>(<span class="regexp">/=/g</span>, <span class="string">&#x27;&#x27;</span>)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">toBase64</span>(<span class="params">value</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="title function_">toBase64URL</span>(<span class="title class_">Buffer</span>.<span class="title function_">from</span>(<span class="title class_">JSON</span>.<span class="title function_">stringify</span>(value)).<span class="title function_">toString</span>(<span class="string">&#x27;base64&#x27;</span>))</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">encode</span>(<span class="params">payload, secret</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> p1 = <span class="variable language_">this</span>.<span class="title function_">toBase64</span>(&#123; <span class="attr">typ</span>: <span class="string">&#x27;JWT&#x27;</span>, <span class="attr">alg</span>: <span class="string">&#x27;HS256&#x27;</span> &#125;);</span><br><span class="line">        <span class="keyword">let</span> p2 = <span class="variable language_">this</span>.<span class="title function_">toBase64</span>(payload);</span><br><span class="line">        <span class="keyword">let</span> p3 = <span class="variable language_">this</span>.<span class="title function_">toBase64URL</span>(<span class="variable language_">this</span>.<span class="title function_">sign</span>(p1 + <span class="string">&#x27;.&#x27;</span> + p2, secret)); <span class="comment">// 就是一个签名</span></span><br><span class="line">        <span class="keyword">return</span> [p1, p2, p3].<span class="title function_">join</span>(<span class="string">&#x27;.&#x27;</span>)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">decode</span>(<span class="params">token, secret</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> [p1, p2, p3] = token.<span class="title function_">split</span>(<span class="string">&#x27;.&#x27;</span>);</span><br><span class="line">        <span class="keyword">let</span> newSign = <span class="variable language_">this</span>.<span class="title function_">toBase64URL</span>(<span class="variable language_">this</span>.<span class="title function_">sign</span>(p1 + <span class="string">&#x27;.&#x27;</span> + p2, secret)); <span class="comment">// 就是一个签名</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (newSign === p3) &#123; <span class="comment">// 用户没有篡改令牌，令牌就是我服务器发给你的</span></span><br><span class="line">            <span class="keyword">let</span> payload = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="title class_">Buffer</span>.<span class="title function_">from</span>(p2, <span class="string">&#x27;base64url&#x27;</span>).<span class="title function_">toString</span>())</span><br><span class="line"></span><br><span class="line">            <span class="comment">// 比较签名的目的就是为了防止篡改</span></span><br><span class="line">            <span class="keyword">return</span> payload;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;token error&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> server = http.<span class="title function_">createServer</span>(<span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; query, pathname &#125; = <span class="built_in">require</span>(<span class="string">&#x27;url&#x27;</span>).<span class="title function_">parse</span>(req.<span class="property">url</span>, <span class="literal">true</span>)</span><br><span class="line">    <span class="keyword">if</span> (req.<span class="property">url</span> === <span class="string">&#x27;/login&#x27;</span>) &#123; <span class="comment">// jsonwebtoken 功能很强大可以设置令牌的有效期，信息...</span></span><br><span class="line">        <span class="comment">// 给用户下发一个token</span></span><br><span class="line">        <span class="comment">// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiemYifQ.QVS8BUD3W80v5WtncMP_wOjm8msihqxGx3LUgyTZxt0</span></span><br><span class="line">        <span class="comment">// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiemYifQ.QVS8BUD3W80v5WtncMP_wOjm8msihqxGx3LUgyTZxt0</span></span><br><span class="line">        <span class="keyword">let</span> token = jw.<span class="title function_">encode</span>(&#123; <span class="attr">_id</span>: <span class="string">&#x27;zf&#x27;</span> &#125;, secret)</span><br><span class="line">        res.<span class="title function_">end</span>(token)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (pathname === <span class="string">&#x27;/list&#x27;</span>) &#123; <span class="comment">// 校验用户有没有登录</span></span><br><span class="line">        <span class="keyword">let</span> token = query.<span class="property">token</span>;</span><br><span class="line">        <span class="keyword">if</span> (token) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">// decode 原理就是 获取token， 拿到token 检验 p1 + p2 的内容是否和你传入的前面一致</span></span><br><span class="line">                <span class="keyword">let</span> payload = jw.<span class="title function_">decode</span>(token, secret)</span><br><span class="line"></span><br><span class="line">                <span class="keyword">return</span> res.<span class="title function_">end</span>(<span class="title class_">JSON</span>.<span class="title function_">stringify</span>(payload) + <span class="string">&#x27;ok&#x27;</span>)</span><br><span class="line">            &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">                <span class="keyword">return</span> res.<span class="title function_">end</span>(<span class="string">&#x27;no list&#x27;</span>)</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">        res.<span class="title function_">end</span>(<span class="string">&#x27;no list&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">server.<span class="title function_">listen</span>(<span class="number">3000</span>);</span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="cookie-session-sessionStorage-localStorage的区别"><a href="#cookie-session-sessionStorage-localStorage的区别" class="headerlink" title="cookie session sessionStorage localStorage的区别"></a>cookie session sessionStorage localStorage的区别</h2><ul>
<li><p>sessionStorage 和 localStorage的区别？ 本地存储，都是在浏览器上存储的. 我有一个列表页面，我希望进入到详情页的的时候，可以刷新数据还在。 </p>
<ul>
<li>进入a页面的时候 缓存的是a （localStorage -&gt; a）  刷新a页面的时候 此时就回到了b页面</li>
<li>进入b页面的时候 缓存的是b  (localStorage -&gt; b)</li>
</ul>
</li>
<li><p>使用sessionStorage 会话的级别 每次打开一个页面都是一个典型的会话</p>
<ul>
<li>进入a页面的时候 缓存的是a （a页面中的sessionStorage -&gt; a） </li>
<li>进入b页面的时候 缓存的是b （b页面中的sessionStorage -&gt; b）</li>
</ul>
</li>
</ul>
<blockquote>
<p>我们存储的大小一般在 5M左右。  服务端返回一个登录的令牌。 localStroage来存放令牌。 都是不支持跨域的</p>
</blockquote>
<ul>
<li><p>cookie解决的问题是： http是无状态的，没次请求服务端不知道我是谁。 使用cookie进行会话标识</p>
<ul>
<li>设置后访问服务器时会携带上（cookie不能存放敏感信息）没有意义。 cookie是存放在请求头中，存储cookie过大会导致页面白屏。 cookie默认不能跨域，但是可以支持强制携带cookie， cookie可以在顶级域名和子域名下 相互访问  4k。 都放在cookie里每次请求都会携带，浪费流量</li>
</ul>
</li>
<li><p>session就是服务端创建一个映射表（默认存到内存中， 可以存放敏感信息） session基于cookie的， 发送凭证靠的是cookie，存储敏感信息靠的是session。 如果重启session会丢失 （session需要持久化）</p>
</li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://gitee.com/wieldy/bailment-blog/2022/03/29/cookie-session-jwt/" data-id="cljmgj1ev000dzc9j1k0necs9" data-title="cookie-session-jwt" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-express" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/bailment-blog/2022/03/29/express/" class="article-date">
  <time class="dt-published" datetime="2022-03-29T14:12:00.000Z" itemprop="datePublished">2022-03-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/bailment-blog/2022/03/29/express/">express</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <p><a href="https://gitee.com/wieldy/express.git">仓库地址</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://gitee.com/wieldy/bailment-blog/2022/03/29/express/" data-id="cljmgj1ew000ezc9j1kw2h3hw" data-title="express" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-fs" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/bailment-blog/2022/03/29/fs/" class="article-date">
  <time class="dt-published" datetime="2022-03-29T14:12:00.000Z" itemprop="datePublished">2022-03-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/bailment-blog/2022/03/29/fs/">fs</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <ul>
<li><p>bst</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Node</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">element</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">element</span> = element;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">left</span> = <span class="literal">null</span>;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">right</span> = <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Tree</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">compare</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">root</span> = <span class="literal">null</span>;;</span><br><span class="line">        <span class="keyword">let</span> defaultCompare = <span class="variable language_">this</span>.<span class="property">compare</span>;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">compare</span> = compare || defaultCompare</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">compare</span>(<span class="params">a, b</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> a &lt; b</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">add</span>(<span class="params">element</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">root</span> == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="property">root</span> = <span class="keyword">new</span> <span class="title class_">Node</span>(element);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">// 这里怎么实现比较好呢？</span></span><br><span class="line">            <span class="keyword">let</span> current = <span class="variable language_">this</span>.<span class="property">root</span>; <span class="comment">// 我们需要不停的找当前节点的左边或者右边</span></span><br><span class="line">            <span class="keyword">let</span> parent = <span class="literal">null</span>;</span><br><span class="line">            <span class="keyword">while</span> (current) &#123;</span><br><span class="line">                parent = current; <span class="comment">// 10</span></span><br><span class="line">                <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="title function_">compare</span>(current.<span class="property">element</span>, element)) &#123;</span><br><span class="line">                    current = current.<span class="property">right</span>; <span class="comment">// 比当前值小的 放在右边</span></span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    current = current.<span class="property">left</span> <span class="comment">// 左边</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="title function_">compare</span>(parent.<span class="property">element</span>, element)) &#123;</span><br><span class="line">                parent.<span class="property">right</span> = <span class="keyword">new</span> <span class="title class_">Node</span>(element);</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                parent.<span class="property">left</span> = <span class="keyword">new</span> <span class="title class_">Node</span>(element);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">reverseTree</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> stack = [<span class="variable language_">this</span>.<span class="property">root</span>];</span><br><span class="line">        <span class="keyword">let</span> pointer = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">let</span> current;</span><br><span class="line">        <span class="keyword">while</span> (current = stack[pointer++]) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(current.<span class="property">element</span>);</span><br><span class="line">            <span class="keyword">let</span> temp = current.<span class="property">left</span>; <span class="comment">// 将左边和右边进行一个反转</span></span><br><span class="line">            current.<span class="property">left</span> = current.<span class="property">right</span></span><br><span class="line">            current.<span class="property">right</span> = temp</span><br><span class="line">            <span class="keyword">if</span> (current.<span class="property">left</span>) &#123;</span><br><span class="line">                stack.<span class="title function_">push</span>(current.<span class="property">left</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (current.<span class="property">right</span>) &#123;</span><br><span class="line">                stack.<span class="title function_">push</span>(current.<span class="property">right</span>)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">levelTraversal</span>(<span class="params">visit</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> stack = [<span class="variable language_">this</span>.<span class="property">root</span>];</span><br><span class="line">        <span class="keyword">let</span> pointer = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">let</span> current;</span><br><span class="line">        <span class="keyword">while</span> (current = stack[pointer++]) &#123;</span><br><span class="line">            visit.<span class="title function_">visitor</span>(current);</span><br><span class="line">            <span class="keyword">if</span> (current.<span class="property">left</span>) &#123;</span><br><span class="line">                stack.<span class="title function_">push</span>(current.<span class="property">left</span>);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (current.<span class="property">right</span>) &#123;</span><br><span class="line">                stack.<span class="title function_">push</span>(current.<span class="property">right</span>)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 先序（diff算法 遇到节点就比较当前节点，比较后在操作儿子）  中序（按照从小到大或者从大大小来排列的） 后序 （先处理子，在处理父）</span></span><br><span class="line">    <span class="comment">// 按照先中后的顺序来访问树</span></span><br><span class="line">    <span class="comment">// 非递归方式和层序很像 *可以用栈来实现*</span></span><br><span class="line">    <span class="title function_">preTraversal</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> <span class="title function_">traversal</span> = (<span class="params">root</span>) =&gt; &#123;</span><br><span class="line">            <span class="keyword">if</span> (root == <span class="literal">null</span>) <span class="keyword">return</span>;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(root);</span><br><span class="line">            <span class="title function_">traversal</span>(root.<span class="property">left</span>);</span><br><span class="line">            <span class="title function_">traversal</span>(root.<span class="property">right</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">traversal</span>(<span class="variable language_">this</span>.<span class="property">root</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">inorderTraversal</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> <span class="title function_">traversal</span> = (<span class="params">root</span>) =&gt; &#123;</span><br><span class="line">            <span class="keyword">if</span> (root == <span class="literal">null</span>) <span class="keyword">return</span>;</span><br><span class="line">            <span class="title function_">traversal</span>(root.<span class="property">left</span>);</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(root);</span><br><span class="line">            <span class="title function_">traversal</span>(root.<span class="property">right</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">traversal</span>(<span class="variable language_">this</span>.<span class="property">root</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">postTranversal</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> <span class="title function_">traversal</span> = (<span class="params">root</span>) =&gt; &#123;</span><br><span class="line">            <span class="keyword">if</span> (root == <span class="literal">null</span>) <span class="keyword">return</span>;</span><br><span class="line">            <span class="title function_">traversal</span>(root.<span class="property">left</span>);</span><br><span class="line">            <span class="title function_">traversal</span>(root.<span class="property">right</span>);</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(root);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">traversal</span>(<span class="variable language_">this</span>.<span class="property">root</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 树的遍历有四种方式  先序 中序  后序  层序</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 10 8 6</span></span><br><span class="line"><span class="keyword">let</span> tree = <span class="keyword">new</span> <span class="title class_">Tree</span>(<span class="function">(<span class="params">a, b</span>) =&gt;</span> &#123; <span class="comment">//  遍历的时候 提供比较方法 [].sort(()=&gt;&#123;]&#125;)</span></span><br><span class="line">    <span class="keyword">return</span> b.<span class="property">n</span> - a.<span class="property">n</span> &gt; <span class="number">0</span></span><br><span class="line">&#125;);</span><br><span class="line"><span class="keyword">let</span> arr = [&#123; <span class="attr">n</span>: <span class="number">10</span> &#125;, &#123; <span class="attr">n</span>: <span class="number">8</span> &#125;, &#123; <span class="attr">n</span>: <span class="number">19</span> &#125;, &#123; <span class="attr">n</span>: <span class="number">6</span> &#125;, &#123; <span class="attr">n</span>: <span class="number">15</span> &#125;, &#123; <span class="attr">n</span>: <span class="number">22</span> &#125;, &#123; <span class="attr">n</span>: <span class="number">20</span> &#125;]; <span class="comment">// 二叉搜索树要求 存储的数据必须能有比较性</span></span><br><span class="line">arr.<span class="title function_">forEach</span>(<span class="function"><span class="params">item</span> =&gt;</span> &#123;</span><br><span class="line">    tree.<span class="title function_">add</span>(item);</span><br><span class="line">&#125;); <span class="comment">// 如何实现二叉搜索树</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// babel 遍历语法树的时候  babel.transform </span></span><br><span class="line"><span class="comment">// htmlparser</span></span><br><span class="line">tree.<span class="title function_">inorderTraversal</span>(&#123;</span><br><span class="line">    <span class="title function_">visitor</span>(<span class="params">node</span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(node.<span class="property">element</span>.<span class="property">n</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;); <span class="comment">// 树在前端中最常用的操作就是</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(tree.<span class="property">root</span>)</span><br></pre></td></tr></table></figure>
</li>
<li><p>file</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>).<span class="property">promises</span>;</span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 同步阻塞  异步阻塞</span></span><br><span class="line"><span class="comment">// 带sync都是同步的</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 可以使用fs.stat 或者 fs.access 来判断文件的存在性，如果用同步的可以采用fs.exits</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// access 就是看能不能访问到</span></span><br><span class="line"><span class="comment">// stat  文件状态信息 （是文件和是目录都可以）</span></span><br><span class="line"><span class="comment">// fs.stat(path.resolve(__dirname, &#x27;a&#x27;), function (err, statObj) &#123;</span></span><br><span class="line"><span class="comment">//     if (statObj) &#123;</span></span><br><span class="line"><span class="comment">//         console.log(statObj.isFile(), statObj.isDirectory(), statObj.ctime)</span></span><br><span class="line"><span class="comment">//     &#125;</span></span><br><span class="line"><span class="comment">// &#125;);</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// fs.mkdir(path.resolve(__dirname, &#x27;a/b/c/d/e&#x27;), &#123; recursive: true &#125;, function (err) &#123;</span></span><br><span class="line"><span class="comment">//     console.log(err)</span></span><br><span class="line"><span class="comment">// &#125;)</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// fs.rmdir(path.resolve(__dirname, &#x27;a&#x27;), &#123; recursive: true &#125;, function (err) &#123;</span></span><br><span class="line"><span class="comment">//     console.log(err);</span></span><br><span class="line"><span class="comment">// &#125;)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 读取当前文件夹的子目录</span></span><br><span class="line"><span class="comment">/* fs.readdir(path.resolve(__dirname, &#x27;a&#x27;), function (err, dirs) &#123;</span></span><br><span class="line"><span class="comment">    dirs = dirs.map(dir =&gt; path.join(&#x27;a&#x27;, dir));</span></span><br><span class="line"><span class="comment">    dirs.forEach(dir =&gt; &#123;</span></span><br><span class="line"><span class="comment">        fs.stat(dir, function (err, statObj) &#123;</span></span><br><span class="line"><span class="comment">            if (statObj.isDirectory()) &#123;</span></span><br><span class="line"><span class="comment">                fs.rmdir(dir, () =&gt; &#123; &#125;)</span></span><br><span class="line"><span class="comment">            &#125; else &#123;</span></span><br><span class="line"><span class="comment">                fs.unlink(dir, () =&gt; &#123; &#125;)</span></span><br><span class="line"><span class="comment">            &#125;</span></span><br><span class="line"><span class="comment">        &#125;)</span></span><br><span class="line"><span class="comment">    &#125;);</span></span><br><span class="line"><span class="comment">    // 孩子删除后在删除自己</span></span><br><span class="line"><span class="comment">&#125;) */</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// fs.rmdir(path.resolve(__dirname, &#x27;a&#x27;), function (err) &#123;</span></span><br><span class="line"><span class="comment">//     console.log(err);</span></span><br><span class="line"><span class="comment">// &#125;)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//  一步步优化逻辑，  就放弃回调。  callback -&gt; async + await</span></span><br><span class="line"><span class="comment">/* function rmdir(dirname, cb) &#123;</span></span><br><span class="line"><span class="comment">    fs.stat(dirname, function (err, statObj) &#123;</span></span><br><span class="line"><span class="comment">        if (err) &#123;</span></span><br><span class="line"><span class="comment">            return cb(err);</span></span><br><span class="line"><span class="comment">        &#125;</span></span><br><span class="line"><span class="comment">        if (statObj.isFile()) &#123;</span></span><br><span class="line"><span class="comment">            fs.unlink(dirname, cb);</span></span><br><span class="line"><span class="comment">        &#125; else &#123;</span></span><br><span class="line"><span class="comment">            // 文件夹</span></span><br><span class="line"><span class="comment">            // 读取文件夹中的内容看一下有没有孩子节点</span></span><br><span class="line"><span class="comment">            fs.readdir(dirname, function (err, dirs) &#123; // 读出 a 目录下的b和c</span></span><br><span class="line"><span class="comment">                dirs = dirs.map(dir =&gt; path.join(dirname, dir)); // 映射路径 a/b  a/c</span></span><br><span class="line"><span class="comment">                let idx = 0;</span></span><br><span class="line"><span class="comment">                function next() &#123;</span></span><br><span class="line"><span class="comment">                    if (idx == dirs.length) return fs.rmdir(dirname, cb); // 子都删除完毕后删除父亲</span></span><br><span class="line"><span class="comment">                    let currentDeleteDir = dirs[idx++]; // 先取出a/b来删除  a/c</span></span><br><span class="line"><span class="comment">                    rmdir(currentDeleteDir, next)</span></span><br><span class="line"><span class="comment">                &#125;</span></span><br><span class="line"><span class="comment">                next(); // 异步迭代需要采用next方法  co 串行</span></span><br><span class="line"><span class="comment">            &#125;)</span></span><br><span class="line"><span class="comment">        &#125;</span></span><br><span class="line"><span class="comment">    &#125;)</span></span><br><span class="line"><span class="comment">&#125; */</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* function rmdir(dirname, cb) &#123;</span></span><br><span class="line"><span class="comment">    fs.stat(dirname, function (err, statObj) &#123;</span></span><br><span class="line"><span class="comment">        if (err) &#123;</span></span><br><span class="line"><span class="comment">            return cb(err);</span></span><br><span class="line"><span class="comment">        &#125;</span></span><br><span class="line"><span class="comment">        if (statObj.isFile()) &#123;</span></span><br><span class="line"><span class="comment">            fs.unlink(dirname, cb);</span></span><br><span class="line"><span class="comment">        &#125; else &#123;</span></span><br><span class="line"><span class="comment">            // 文件夹</span></span><br><span class="line"><span class="comment">            // 读取文件夹中的内容看一下有没有孩子节点</span></span><br><span class="line"><span class="comment">            fs.readdir(dirname, function (err, dirs) &#123; // 读出 a 目录下的b和c</span></span><br><span class="line"><span class="comment">                dirs = dirs.map(dir =&gt; path.join(dirname, dir)); // 映射路径 a/b  a/c</span></span><br><span class="line"><span class="comment">                if (dirs.length === 0) &#123; // 如果目录就是空的直接删除即可</span></span><br><span class="line"><span class="comment">                    return fs.rmdir(dirname, cb)</span></span><br><span class="line"><span class="comment">                &#125;</span></span><br><span class="line"><span class="comment">                let times = 0;</span></span><br><span class="line"><span class="comment">                function done() &#123;</span></span><br><span class="line"><span class="comment">                    if (++times === dirs.length) &#123;</span></span><br><span class="line"><span class="comment">                        fs.rmdir(dirname, cb)</span></span><br><span class="line"><span class="comment">                    &#125;</span></span><br><span class="line"><span class="comment">                &#125;</span></span><br><span class="line"><span class="comment">                dirs.forEach(dir =&gt; &#123; // a/b  a/c    异步并行 for循环是并行的  递归是串行的</span></span><br><span class="line"><span class="comment">                    rmdir(dir, done)</span></span><br><span class="line"><span class="comment">                &#125;)</span></span><br><span class="line"><span class="comment">            &#125;)</span></span><br><span class="line"><span class="comment">        &#125;</span></span><br><span class="line"><span class="comment">    &#125;)</span></span><br><span class="line"><span class="comment">&#125; */</span></span><br><span class="line"><span class="comment">/* function rmdir(dirname) &#123;</span></span><br><span class="line"><span class="comment">    return new Promise((resolve, reject) =&gt; &#123;</span></span><br><span class="line"><span class="comment">        fs.stat(dirname, function (err, statObj) &#123;</span></span><br><span class="line"><span class="comment">            if (err) &#123;</span></span><br><span class="line"><span class="comment">                return reject(err);</span></span><br><span class="line"><span class="comment">            &#125;</span></span><br><span class="line"><span class="comment">            if (statObj.isFile()) &#123;</span></span><br><span class="line"><span class="comment">                fs.unlink(dirname, resolve);</span></span><br><span class="line"><span class="comment">            &#125; else &#123;</span></span><br><span class="line"><span class="comment">                // 文件夹</span></span><br><span class="line"><span class="comment">                // 读取文件夹中的内容看一下有没有孩子节点</span></span><br><span class="line"><span class="comment">                fs.readdir(dirname, function (err, dirs) &#123; // 读出 a 目录下的b和c</span></span><br><span class="line"><span class="comment">                    Promise.all(dirs.map(dir =&gt; rmdir(path.join(dirname, dir)))).then(() =&gt; &#123;</span></span><br><span class="line"><span class="comment">                        fs.rmdir(dirname, resolve)</span></span><br><span class="line"><span class="comment">                    &#125;);</span></span><br><span class="line"><span class="comment">                &#125;)</span></span><br><span class="line"><span class="comment">            &#125;</span></span><br><span class="line"><span class="comment">        &#125;)</span></span><br><span class="line"><span class="comment">    &#125;)</span></span><br><span class="line"><span class="comment">&#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="comment">// 全部async + await  + promise 来实现代码逻辑</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">rmdir</span>(<span class="params">dirname</span>) &#123; <span class="comment">// 异步并发</span></span><br><span class="line">    <span class="keyword">let</span> statObj = <span class="keyword">await</span> fs.<span class="title function_">stat</span>(dirname)</span><br><span class="line">    <span class="keyword">if</span> (statObj.<span class="title function_">isFile</span>()) &#123;</span><br><span class="line">        <span class="keyword">return</span> fs.<span class="title function_">unlink</span>(dirname);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">let</span> dirs = <span class="keyword">await</span> fs.<span class="title function_">readdir</span>(dirname);</span><br><span class="line">        <span class="keyword">await</span> <span class="title class_">Promise</span>.<span class="title function_">all</span>(dirs.<span class="title function_">map</span>(<span class="function"><span class="params">dir</span> =&gt;</span> <span class="title function_">rmdir</span>(path.<span class="title function_">join</span>(dirname, dir))))</span><br><span class="line">        <span class="keyword">return</span> fs.<span class="title function_">rmdir</span>(dirname)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 如果是同步的删除 可以考虑层序遍历 + 倒序删除</span></span><br><span class="line"><span class="title function_">rmdir</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&#x27;a&#x27;</span>)).<span class="title function_">then</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;删除成功&#x27;</span>)</span><br><span class="line">&#125;).<span class="title function_">catch</span>(<span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(e)</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// fs.stat  fs.readdir  fs.rmdir fs.unlink  遍历</span></span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="常见的数据结构-（存储数据）"><a href="#常见的数据结构-（存储数据）" class="headerlink" title="常见的数据结构  （存储数据）"></a>常见的数据结构  （存储数据）</h2><ul>
<li>线性结构 查询节点的时候 需要依次遍历 O(n)  线性结构典型的有：队列 、栈 、链表</li>
<li>树结构： 二叉树，存储方式可以通过二分查找来进行搜索  (二叉搜索树)  插入和查询 O(logn)</li>
<li>开发中接触的比较多的。多叉树： DOM树， 文件夹操作（树组件， 节点的访问） babel ast语法树， 路由配置。。。。</li>
</ul>
<blockquote>
<p>二叉搜索树的概念，存储的时候 按照大小进行排列 （二叉排序树）</p>
</blockquote>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://gitee.com/wieldy/bailment-blog/2022/03/29/fs/" data-id="cljmgj1ew000fzc9j5982gdc9" data-title="fs" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-http" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/bailment-blog/2022/03/29/http/" class="article-date">
  <time class="dt-published" datetime="2022-03-29T14:12:00.000Z" itemprop="datePublished">2022-03-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/bailment-blog/2022/03/29/http/">http</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <ul>
<li><p>net</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> net = <span class="built_in">require</span>(<span class="string">&#x27;net&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 我们只是做了一层封装</span></span><br><span class="line"><span class="keyword">const</span> server = net.<span class="title function_">createServer</span>(<span class="keyword">function</span> (<span class="params">socket</span>) &#123;</span><br><span class="line">    socket.<span class="title function_">on</span>(<span class="string">&#x27;data&#x27;</span>, <span class="keyword">function</span> (<span class="params">data</span>) &#123;</span><br><span class="line">        <span class="comment">// 请求行：请求方法 请求路径 版本号</span></span><br><span class="line">        <span class="comment">// 请求头：key: value</span></span><br><span class="line">        <span class="comment">// 空行</span></span><br><span class="line">        <span class="comment">// 请求体</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 响应行： 版本号  状态码</span></span><br><span class="line">        socket.<span class="title function_">end</span>(<span class="string">`</span></span><br><span class="line"><span class="string">            HTTP/1.1 200 OK</span></span><br><span class="line"><span class="string">            Content-Length: 5</span></span><br><span class="line"><span class="string">            hello</span></span><br><span class="line"><span class="string">        `</span>)</span><br><span class="line">    &#125;);</span><br><span class="line">    socket.<span class="title function_">on</span>(<span class="string">&#x27;end&#x27;</span>, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line"></span><br><span class="line">    &#125;)</span><br><span class="line">&#125;)</span><br><span class="line">server.<span class="title function_">on</span>(<span class="string">&#x27;error&#x27;</span>, <span class="keyword">function</span> (<span class="params">err</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(err);</span><br><span class="line">&#125;)</span><br><span class="line">server.<span class="title function_">listen</span>(<span class="number">8080</span>); <span class="comment">// 监听8080端口</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 用工具监听文件变化，文件变化后可以自动重启</span></span><br><span class="line"><span class="comment">// nodemon  pm2 supervisor ...</span></span><br><span class="line"><span class="comment">// npm install nodemon -g</span></span><br><span class="line"><span class="comment">// nodemon 1.net.js</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>server</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">const</span> http = <span class="built_in">require</span>(<span class="string">&#x27;http&#x27;</span>); <span class="comment">// 内置的模块 专门处理http请求的</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 底层基于net模块（基于tcp来实现的，请求到来的时候会触发socket来监听数据到来，手动解析用户的参数）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 这是基于http实现的服务器，将报文已经解析好了</span></span><br><span class="line"><span class="comment">// req代表客户端的内容 </span></span><br><span class="line"><span class="comment">// res代表的是要给响应写数据</span></span><br><span class="line"><span class="keyword">let</span> server = http.<span class="title function_">createServer</span>(<span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123; <span class="comment">// req.push(123)  req.push(null)</span></span><br><span class="line">    <span class="comment">// 请求方法 请求路径 版本号</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(req.<span class="property">method</span>); <span class="comment">// 获取请求的方法  请求方法是大写的 </span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(req.<span class="property">url</span>); <span class="comment">// 路径是包含查询参数的,不会获取到hash值 （hash路由是不能做seo优化的）</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(req.<span class="property">httpVersion</span>); <span class="comment">// 版本号</span></span><br><span class="line">    <span class="keyword">let</span> arr = [];</span><br><span class="line">    req.<span class="title function_">on</span>(<span class="string">&#x27;data&#x27;</span>, <span class="keyword">function</span> (<span class="params">chunk</span>) &#123;</span><br><span class="line">        arr.<span class="title function_">push</span>(chunk);</span><br><span class="line">    &#125;);</span><br><span class="line">    req.<span class="title function_">on</span>(<span class="string">&#x27;end&#x27;</span>, <span class="keyword">function</span> (<span class="params">chunk</span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title class_">Buffer</span>.<span class="title function_">concat</span>(arr).<span class="title function_">toString</span>())</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="comment">// 请求相关的信息</span></span><br><span class="line">    <span class="comment">// 解析响应相关的</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// res.statusCode = 454; // 状态码可以瞎写 就失去了意义</span></span><br><span class="line">    <span class="comment">// res.statusMessage = &#x27;wusiwu&#x27;</span></span><br><span class="line">    res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Content-Type&#x27;</span>, <span class="string">&#x27;text/plain;charset=utf-8&#x27;</span>);</span><br><span class="line">    res.<span class="title function_">write</span>(<span class="string">&#x27;hello&#x27;</span>);</span><br><span class="line">    res.<span class="title function_">write</span>(<span class="string">&#x27;world&#x27;</span>);</span><br><span class="line">    res.<span class="title function_">end</span>(<span class="string">&#x27;你好&#x27;</span>);</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// server.on(&#x27;request&#x27;, function () &#123;</span></span><br><span class="line"><span class="comment">//     console.log(&#x27;request1&#x27;)</span></span><br><span class="line"><span class="comment">// &#125;)</span></span><br><span class="line"><span class="keyword">let</span> port = <span class="number">3000</span>;</span><br><span class="line">server.<span class="title function_">listen</span>(port, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;server start &#x27;</span> + port);</span><br><span class="line">&#125;);</span><br><span class="line">server.<span class="title function_">on</span>(<span class="string">&#x27;error&#x27;</span>, <span class="keyword">function</span> (<span class="params">err</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (err &amp;&amp; err.<span class="property">code</span> === <span class="string">&#x27;EADDRINUSE&#x27;</span>) &#123; <span class="comment">// 可以监听端口号被占用 重新监听一个请求</span></span><br><span class="line">        server.<span class="title function_">listen</span>(++port)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
</li>
<li><p>mock</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = <span class="keyword">function</span> (<span class="params">pathname, req, res</span>) &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (pathname === <span class="string">&#x27;/user&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (req.<span class="property">method</span> === <span class="string">&#x27;GET&#x27;</span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(req.<span class="property">query</span>);</span><br><span class="line">            res.<span class="title function_">end</span>(<span class="string">&#x27;ok&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (req.<span class="property">method</span> === <span class="string">&#x27;POST&#x27;</span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(req.<span class="property">body</span>);</span><br><span class="line">            res.<span class="title function_">end</span>(<span class="string">&#x27;ok&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (req.<span class="property">method</span> === <span class="string">&#x27;DELETE&#x27;</span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(req.<span class="property">body</span>);</span><br><span class="line">            res.<span class="title function_">end</span>(<span class="string">&#x27;OK&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>test.html</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> xhr = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>();</span><br><span class="line">        xhr.<span class="title function_">open</span>(<span class="string">&#x27;DELETE&#x27;</span>, <span class="string">&#x27;http://localhost:8080/user&#x27;</span>, <span class="literal">true</span>);</span><br><span class="line">        <span class="comment">// 默认get和post请求是简单请求，我们设置了自定义的header 复杂请求 （内置的header不会变为复杂请求)</span></span><br><span class="line">        xhr.<span class="title function_">setRequestHeader</span>(<span class="string">&#x27;authorization&#x27;</span>, <span class="string">&#x27;aaa&#x27;</span>)</span><br><span class="line">        xhr.<span class="property">onload</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(xhr.<span class="property">response</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        xhr.<span class="title function_">send</span>();</span><br></pre></td></tr></table></figure>
</li>
<li><p>zip</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> zlib = <span class="built_in">require</span>(<span class="string">&#x27;zlib&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>);</span><br><span class="line"><span class="comment">// 原理就是将内容进行替换 重复性越高的内容，压缩后越小  大文件视频也不适合gzip方式</span></span><br><span class="line"><span class="comment">// let buffer = fs.readFileSync(&#x27;./1.txt&#x27;);</span></span><br><span class="line"><span class="comment">// 一般情况 js  css 都会去做gzip压缩 让体积变小</span></span><br><span class="line"><span class="comment">// zlib.gzip(buffer, function (err, result) &#123;</span></span><br><span class="line"><span class="comment">//     console.log(err)</span></span><br><span class="line"><span class="comment">//     fs.writeFileSync(&#x27;./2.txt.gz&#x27;, result)</span></span><br><span class="line"><span class="comment">// &#125;)</span></span><br><span class="line">fs.<span class="title function_">createReadStream</span>(<span class="string">&#x27;1.txt&#x27;</span>).<span class="title function_">pipe</span>(zlib.<span class="title function_">createGzip</span>()).<span class="title function_">pipe</span>(fs.<span class="title function_">createWriteStream</span>(<span class="string">&#x27;./2.txt.gz&#x27;</span>))</span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="http中的重点在于报文"><a href="#http中的重点在于报文" class="headerlink" title="http中的重点在于报文"></a>http中的重点在于报文</h2><ul>
<li><p>简单描述一下 请求的发送 “域名”  <a target="_blank" rel="noopener" href="http://www.baidu.com/">www.baidu.com</a>  解析成ip地址  192.168.x.x   “DNS解析服务”</p>
</li>
<li><p>顶级域名  根dns服务器可以进行域名解析  （域名解析的时候采用的是DNS 方向递归查找，找到对应的服务）</p>
</li>
<li><p>状态码：  服务器设置 （但是是约定的）</p>
<ul>
<li>101 websocket  升级 更新</li>
<li>200 200 成功 204 没有响应体 206范围请求 （可以实现断点续传，播放视频）</li>
<li>3xx 301(永久重定向  确定好了定向的目标永远指向到那里) 302 （临时跳转） 307类似（临时重定向）  304 缓存 协商缓存</li>
<li>400 400 客户端代码出错  401 （没有登录 没有权限） 403 （登录过没有权限）  404 找不到  405 （方法不允许）  415 服务器不支持的格式</li>
<li>500 服务端出错 502 、 504 没有响应   503 请求超载</li>
</ul>
</li>
<li><p>准备好请求报文   </p>
<ul>
<li>请求行 请求的方法 路径 版本号</li>
<li>请求头 描述我们发送数据的格式，可以携带一些信息 （重点）</li>
<li>请求体 表单 a&#x3D;b&amp;b&#x3D;c&amp;c&#x3D;d  json 格式   二进制数据格式</li>
</ul>
</li>
<li><p>安全？ http1.1 没有考虑按问题 https 数据进行指纹验证，秘钥。。。</p>
</li>
<li><p>准备好的数据 要经过传输层进行传输 tcp  将数据进行分段传输 增加序号 。。。。。</p>
</li>
<li><p>找到对方 ip层 通过路由跳转和寻址找到对方 </p>
</li>
<li><p>通过物理设备进行传输 </p>
</li>
<li><p>服务端收到消息后 会进行拆包</p>
</li>
<li><p>准备好响应报文</p>
<ul>
<li>响应行 状态码 相应短语  版本号</li>
<li>响应头 描述响应内容的</li>
<li>响应体 具体的响应内容</li>
</ul>
</li>
</ul>
<h2 id="实现一个http-server"><a href="#实现一个http-server" class="headerlink" title="实现一个http-server"></a>实现一个http-server</h2><p>可以在本地启动一个静态服务 </p>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://gitee.com/wieldy/bailment-blog/2022/03/29/http/" data-id="cljmgj1ew000gzc9j70op0qbd" data-title="http" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-http手写" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/bailment-blog/2022/03/29/http%E6%89%8B%E5%86%99/" class="article-date">
  <time class="dt-published" datetime="2022-03-29T14:12:00.000Z" itemprop="datePublished">2022-03-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/bailment-blog/2022/03/29/http%E6%89%8B%E5%86%99/">http</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> http = <span class="built_in">require</span>(<span class="string">&#x27;http&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>).<span class="property">promises</span>;</span><br><span class="line"><span class="keyword">const</span> &#123; createReadStream &#125; = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> zlib = <span class="built_in">require</span>(<span class="string">&#x27;zlib&#x27;</span>)</span><br><span class="line"><span class="comment">// const url = require(&#x27;url&#x27;); // req.url 有 query</span></span><br><span class="line"><span class="keyword">const</span> os = <span class="built_in">require</span>(<span class="string">&#x27;os&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> querystring = <span class="built_in">require</span>(<span class="string">&#x27;querystring&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// --------------------------</span></span><br><span class="line"><span class="keyword">const</span> chalk = <span class="built_in">require</span>(<span class="string">&#x27;chalk&#x27;</span>); <span class="comment">// 粉笔 可以展现不同的颜色</span></span><br><span class="line"><span class="keyword">const</span> parse = <span class="built_in">require</span>(<span class="string">&#x27;url-parse&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> debug = <span class="built_in">require</span>(<span class="string">&#x27;debug&#x27;</span>)(<span class="string">&#x27;http&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> mime = <span class="built_in">require</span>(<span class="string">&#x27;mime&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> ejs = <span class="built_in">require</span>(<span class="string">&#x27;ejs&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 多语言 语言表</span></span><br><span class="line"><span class="keyword">const</span> messages = &#123;</span><br><span class="line">    <span class="attr">en</span>: <span class="string">&#x27;hello world&#x27;</span>,</span><br><span class="line">    <span class="attr">ja</span>: <span class="string">&#x27;こんにちは、世界&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 就是两个网站 通过url来区分 是什么语言 /zh-CN  /en</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Server</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">options = &#123;&#125;</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">port</span> = options.<span class="property">port</span>;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">directory</span> = options.<span class="property">directory</span>;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">address</span> = options.<span class="property">address</span></span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">start</span>();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">processReqData</span>(<span class="params">req</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">const</span> arr = [];</span><br><span class="line">            req.<span class="title function_">on</span>(<span class="string">&#x27;data&#x27;</span>, <span class="keyword">function</span> (<span class="params">chunk</span>) &#123;</span><br><span class="line">                arr.<span class="title function_">push</span>(chunk);</span><br><span class="line">            &#125;);</span><br><span class="line">            req.<span class="title function_">on</span>(<span class="string">&#x27;end&#x27;</span>, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">                <span class="comment">// 客户端告诉服务器如何解析数据</span></span><br><span class="line">                <span class="keyword">let</span> data = <span class="title class_">Buffer</span>.<span class="title function_">concat</span>(arr).<span class="title function_">toString</span>();</span><br><span class="line">                <span class="keyword">let</span> contentType = req.<span class="property">headers</span>[<span class="string">&#x27;content-type&#x27;</span>];</span><br><span class="line">                <span class="keyword">if</span> (contentType === <span class="string">&#x27;application/x-www-form-urlencoded&#x27;</span>) &#123;</span><br><span class="line">                    <span class="comment">// a=b&amp;c=d  =&gt; &#123;a:b,c:d&#125;  qs</span></span><br><span class="line">                    <span class="title function_">resolve</span>(querystring.<span class="title function_">parse</span>(data))</span><br><span class="line">                &#125; <span class="keyword">else</span> <span class="keyword">if</span> (contentType === <span class="string">&#x27;application/json&#x27;</span>) &#123;</span><br><span class="line">                    <span class="title function_">resolve</span>(<span class="title class_">JSON</span>.<span class="title function_">parse</span>(data))</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="title function_">resolve</span>(&#123;&#125;)</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">async</span> <span class="title function_">request</span>(<span class="params">pathname, query, req, res</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> mock = path.<span class="title function_">resolve</span>(<span class="variable language_">this</span>.<span class="property">directory</span>, <span class="string">&#x27;mock.js&#x27;</span>);</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">await</span> fs.<span class="title function_">stat</span>(mock);</span><br><span class="line">            req.<span class="property">body</span> = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">processReqData</span>(req); <span class="comment">// 请求体的数据</span></span><br><span class="line">            req.<span class="property">query</span> = query;</span><br><span class="line">            <span class="keyword">let</span> mockFn = <span class="built_in">require</span>(mock)</span><br><span class="line">            <span class="keyword">return</span> <span class="title function_">mockFn</span>(pathname, req, res)</span><br><span class="line">        &#125; <span class="keyword">catch</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    handleRequest = <span class="keyword">async</span> (req, res) =&gt; &#123; <span class="comment">// 处理客户端的请求  和响应客户端</span></span><br><span class="line">        <span class="comment">// 获取用户的路径 </span></span><br><span class="line">        <span class="keyword">let</span> &#123; pathname, query &#125; = <span class="title function_">parse</span>(req.<span class="property">url</span>, <span class="literal">true</span>)</span><br><span class="line">        <span class="comment">// cors</span></span><br><span class="line">        <span class="keyword">if</span> (req.<span class="property">headers</span>.<span class="property">origin</span>) &#123; <span class="comment">// 可以看origin值是否有值，有值则是出现了跨域问题</span></span><br><span class="line">            res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Access-Control-Allow-Origin&#x27;</span>, req.<span class="property">headers</span>.<span class="property">origin</span>); <span class="comment">// 写*在有cookie的情况是不可以的</span></span><br><span class="line">            res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Access-Control-Allow-Headers&#x27;</span>, <span class="string">&#x27;authorization&#x27;</span>)</span><br><span class="line">            res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Access-Control-Max-Age&#x27;</span>, <span class="string">&#x27;10&#x27;</span>); <span class="comment">// 10才发一次options get/post + 自定义header  发送的请求不是get或者post</span></span><br><span class="line">            res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Access-Control-Allow-Methods&#x27;</span>, <span class="string">&#x27;GET,POST,PUT,DELETE,OPTIONS&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (req.<span class="property">method</span> === <span class="string">&#x27;OPTIONS&#x27;</span>) &#123; <span class="comment">// 服务端遇到options 返回ok即可</span></span><br><span class="line">            <span class="keyword">return</span> res.<span class="title function_">end</span>();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">let</span> flag = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="title function_">request</span>(pathname, query, req, res)</span><br><span class="line">        <span class="keyword">if</span> (flag) &#123;</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 根据目录读取  mock数据 </span></span><br><span class="line">        <span class="keyword">if</span> (pathname === <span class="string">&#x27;/hello&#x27;</span>) &#123; <span class="comment">// 实现多语言</span></span><br><span class="line">            <span class="keyword">let</span> lans = req.<span class="property">headers</span>[<span class="string">&#x27;accept-language&#x27;</span>];</span><br><span class="line">            <span class="comment">// zh-CN,zh;q=0.9,es;q=0.8 </span></span><br><span class="line">            <span class="keyword">const</span> langObj = lans.<span class="title function_">split</span>(<span class="string">&#x27;,&#x27;</span>).<span class="title function_">map</span>(<span class="function"><span class="params">lan</span> =&gt;</span> &#123;</span><br><span class="line">                <span class="keyword">let</span> [name, q = <span class="string">&#x27;q=1&#x27;</span>] = lan.<span class="title function_">split</span>(<span class="string">&#x27;;&#x27;</span>);</span><br><span class="line">                <span class="keyword">return</span> &#123; name, <span class="attr">q</span>: q.<span class="title function_">split</span>(<span class="string">&#x27;=&#x27;</span>)[<span class="number">1</span>] &#125;;</span><br><span class="line">            &#125;).<span class="title function_">sort</span>(<span class="function">(<span class="params">a, b</span>) =&gt;</span> b.<span class="property">q</span> - a.<span class="property">q</span>)</span><br><span class="line"></span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; langObj.<span class="property">length</span>; i++) &#123;</span><br><span class="line">                <span class="keyword">let</span> lan = messages[langObj[i].<span class="property">name</span>];</span><br><span class="line">                <span class="keyword">if</span> (lan) &#123;</span><br><span class="line">                    <span class="keyword">return</span> res.<span class="title function_">end</span>(lan);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> res.<span class="title function_">end</span>(messages[<span class="string">&#x27;en&#x27;</span>])</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="comment">// referer的处理 有些图片只能在我的域名下访问，不能被别人的网站去访问。 防盗链</span></span><br><span class="line">        <span class="comment">// referer || referrer  两个都支持一下</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (<span class="regexp">/\.(webp)/</span>.<span class="title function_">test</span>(pathname)) &#123;</span><br><span class="line">            <span class="keyword">let</span> referer = req.<span class="property">headers</span>[<span class="string">&#x27;referer&#x27;</span>] || req.<span class="property">headers</span>[<span class="string">&#x27;referrer&#x27;</span>];</span><br><span class="line">            <span class="keyword">let</span> whiteList = []</span><br><span class="line">            <span class="keyword">if</span> (referer) &#123; <span class="comment">// 说明有人引用我的资源了， 我需要检验一下</span></span><br><span class="line">                <span class="keyword">let</span> hostname = <span class="string">&#x27;http://&#x27;</span> + req.<span class="property">headers</span>[<span class="string">&#x27;host&#x27;</span>];</span><br><span class="line">                <span class="keyword">let</span> a1 = <span class="title function_">parse</span>(hostname).<span class="property">hostname</span>;</span><br><span class="line">                <span class="keyword">let</span> a2 = <span class="title function_">parse</span>(referer).<span class="property">hostname</span>;</span><br><span class="line">                <span class="keyword">if</span> (a1 !== a2 || whiteList.<span class="title function_">includes</span>(<span class="string">&#x27;xxx&#x27;</span>)) &#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="title function_">createReadStream</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&#x27;error.webp&#x27;</span>)).<span class="title function_">pipe</span>(res);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 静态服务----------------------------------------</span></span><br><span class="line">            <span class="keyword">let</span> queryPath = path.<span class="title function_">join</span>(<span class="variable language_">this</span>.<span class="property">directory</span>, pathname);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">let</span> statObj = <span class="keyword">await</span> fs.<span class="title function_">stat</span>(queryPath);</span><br><span class="line">            <span class="keyword">if</span> (statObj.<span class="title function_">isFile</span>()) &#123;</span><br><span class="line">                <span class="variable language_">this</span>.<span class="title function_">sendFile</span>(queryPath, req, res, statObj)</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">// 根据路径读取路径对应的目录</span></span><br><span class="line">                <span class="keyword">let</span> dirs = <span class="keyword">await</span> fs.<span class="title function_">readdir</span>(queryPath);</span><br><span class="line">                <span class="keyword">let</span> fileStatus = <span class="keyword">await</span> <span class="title class_">Promise</span>.<span class="title function_">all</span>(dirs.<span class="title function_">map</span>(<span class="keyword">async</span> dir =&gt; <span class="keyword">await</span> fs.<span class="title function_">stat</span>(path.<span class="title function_">join</span>(queryPath, dir))));</span><br><span class="line">                dirs = dirs.<span class="title function_">map</span>(<span class="function">(<span class="params">dir, index</span>) =&gt;</span> &#123;</span><br><span class="line">                    <span class="keyword">return</span> &#123;</span><br><span class="line">                        <span class="attr">url</span>: path.<span class="title function_">join</span>(pathname, dir),</span><br><span class="line">                        dir,</span><br><span class="line">                        <span class="attr">info</span>: fileStatus[index].<span class="title function_">isFile</span>() ? <span class="string">&#x27;文件&#x27;</span> : <span class="string">&#x27;文件夹&#x27;</span>,</span><br><span class="line">                        <span class="attr">size</span>: fileStatus[index].<span class="property">size</span> == <span class="number">0</span> ? <span class="string">&#x27;&#x27;</span> : fileStatus[index].<span class="property">size</span></span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;);</span><br><span class="line">                <span class="comment">// 可以使用模板引擎来进行数据渲染 ejs  handlerbar jade nunjucks underscore</span></span><br><span class="line">                <span class="keyword">let</span> html = <span class="keyword">await</span> ejs.<span class="title function_">renderFile</span>(path.<span class="title function_">resolve</span>(__dirname, <span class="string">&#x27;./template.html&#x27;</span>), &#123; dirs &#125;);</span><br><span class="line">                res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Content-Type&#x27;</span>, <span class="string">&#x27;text/html;charset=utf-8&#x27;</span>)</span><br><span class="line">                res.<span class="title function_">end</span>(html);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">            <span class="variable language_">this</span>.<span class="title function_">sendError</span>(e, res)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">cache</span>(<span class="params">queryPath, statObj, req, res</span>) &#123;</span><br><span class="line">        <span class="comment">// 默认5s内 不像服务端发送请求 </span></span><br><span class="line">        res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Cache-Control&#x27;</span>, <span class="string">&#x27;max-age=5&#x27;</span>); <span class="comment">// 5s 内不再发送请求</span></span><br><span class="line">        <span class="keyword">let</span> etag = statObj.<span class="property">size</span> + <span class="string">&#x27;-&#x27;</span> + statObj.<span class="property">ctime</span>.<span class="title function_">getTime</span>();</span><br><span class="line">        res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Etag&#x27;</span>, etag); <span class="comment">// 设置etag</span></span><br><span class="line">        <span class="keyword">let</span> ifNoneMatch = req.<span class="property">headers</span>[<span class="string">&#x27;if-none-match&#x27;</span>];</span><br><span class="line">        <span class="keyword">if</span> (ifNoneMatch == etag) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">gzip</span>(<span class="params">queryPath, req, res</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (!<span class="regexp">/\.(css|js|txt|html)/</span>.<span class="title function_">test</span>(queryPath)) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>; <span class="comment">// 不是html这些类型 不进行压缩处理</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 内容协商</span></span><br><span class="line">        <span class="keyword">let</span> encoding = req.<span class="property">headers</span>[<span class="string">&#x27;accept-encoding&#x27;</span>]; <span class="comment">// 浏览器自己加的 </span></span><br><span class="line">        <span class="keyword">if</span> (encoding.<span class="title function_">includes</span>(<span class="string">&#x27;gzip&#x27;</span>)) &#123;</span><br><span class="line">            res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Content-Encoding&#x27;</span>, <span class="string">&#x27;gzip&#x27;</span>); <span class="comment">// 告诉浏览器用什么方式来进行解析</span></span><br><span class="line">            <span class="keyword">return</span> zlib.<span class="title function_">createGzip</span>();  <span class="comment">// zlib.createDeflate  zlib.createBrotliCompress</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">sendFile</span>(<span class="params">queryPath, req, res, statObj</span>) &#123; <span class="comment">// 根据路径创建一个可读流.pipe(res)</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="title function_">cache</span>(queryPath, statObj, req, res)) &#123;</span><br><span class="line">            res.<span class="property">statusCode</span> = <span class="number">304</span>;</span><br><span class="line">            res.<span class="title function_">end</span>()</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 没有缓存就考虑压缩</span></span><br><span class="line">        <span class="keyword">let</span> createGzip;</span><br><span class="line">        res.<span class="title function_">setHeader</span>(<span class="string">&#x27;Content-Type&#x27;</span>, mime.<span class="title function_">getType</span>(queryPath) + <span class="string">&#x27;;charset=utf-8&#x27;</span>)</span><br><span class="line">        <span class="keyword">if</span> (createGzip = <span class="variable language_">this</span>.<span class="title function_">gzip</span>(queryPath, req, res)) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="title function_">createReadStream</span>(queryPath).<span class="title function_">pipe</span>(createGzip).<span class="title function_">pipe</span>(res);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="title function_">createReadStream</span>(queryPath).<span class="title function_">pipe</span>(res);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">sendError</span>(<span class="params">e, res</span>) &#123;</span><br><span class="line">        <span class="comment">// 能根据不同的环境 打印出日志来</span></span><br><span class="line">        <span class="title function_">debug</span>(e);</span><br><span class="line">        res.<span class="title function_">end</span>(<span class="string">&#x27;Not found&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">start</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> server = http.<span class="title function_">createServer</span>(<span class="variable language_">this</span>.<span class="property">handleRequest</span>);</span><br><span class="line">        <span class="keyword">const</span> port = <span class="variable language_">this</span>.<span class="property">port</span>;</span><br><span class="line">        <span class="keyword">const</span> address = <span class="variable language_">this</span>.<span class="property">address</span>.<span class="title function_">map</span>(<span class="function"><span class="params">item</span> =&gt;</span> <span class="string">&#x27;  http://&#x27;</span> + item + <span class="string">&quot;:&quot;</span> + chalk.<span class="title function_">green</span>(port))</span><br><span class="line">        server.<span class="title function_">listen</span>(port, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(chalk.<span class="title function_">yellow</span>(<span class="string">&#x27;Available on:&#x27;</span>))</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(address.<span class="title function_">join</span>(<span class="string">&#x27;\r\n&#x27;</span>));</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`Hit CTRL-C to stop the server`</span>)</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = <span class="keyword">function</span> <span class="title function_">createServer</span>(<span class="params">userConfig</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> interface = os.<span class="title function_">networkInterfaces</span>(); <span class="comment">// 用户接口 </span></span><br><span class="line">    <span class="keyword">const</span> address = <span class="title class_">Object</span>.<span class="title function_">values</span>(interface).<span class="title function_">flat</span>(<span class="number">1</span>).<span class="title function_">filter</span>(<span class="function"><span class="params">item</span> =&gt;</span> item.<span class="property">family</span> === <span class="string">&#x27;IPv4&#x27;</span>).<span class="title function_">map</span>(<span class="function"><span class="params">item</span> =&gt;</span> item.<span class="property">address</span>)</span><br><span class="line">    userConfig[<span class="string">&#x27;address&#x27;</span>] = address</span><br><span class="line">    <span class="comment">// 这里可以对userConfig进行二次处理，处理后使用配置创建服务</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Server</span>(userConfig);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// // 设置强制缓存 不用每一次都请求了 10s内不要在来访问css</span></span><br><span class="line"><span class="comment">//         // res.setHeader(&#x27;Expires&#x27;, new Date(Date.now() + 10 * 1000).toGMTString()); // http1.0</span></span><br><span class="line"><span class="comment">//         // no-cache 不利用缓存 但是缓存了  /  no-store  压根没有缓存</span></span><br><span class="line"><span class="comment">//         res.setHeader(&#x27;Cache-Control&#x27;, &#x27;max-age=0&#x27;); // 10s 内你找浏览器的本地缓存就可以了</span></span><br><span class="line"><span class="comment">//         // 只有引用的资源 才能走强制缓存，默认直接访问的资源不能强制缓存</span></span><br><span class="line"><span class="comment">//         // 首次访问的资源会默认添加 max-age=0 不走强制缓存</span></span><br><span class="line"><span class="comment">//         // 不轻易更改的可以采用强制缓存</span></span><br><span class="line"><span class="comment">//         // 协商缓存  不是直接就不访问了 而是询问一下服务器要不要走缓存</span></span><br><span class="line"><span class="comment">//         let ctime = statObj.ctime.getTime(); // changeTime;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//         // 服务端设置的是last-modified  客户端下一次请求的时候会携带一个if-modified-since</span></span><br><span class="line"><span class="comment">//         // 我可以比较两个时间，如果时间一致 则说明文件没有变化 给状态码304 ，此时浏览器就会找缓存</span></span><br><span class="line"><span class="comment">//         // res.setHeader(&#x27;Last-Modified&#x27;, ctime);</span></span><br><span class="line"><span class="comment">//         // let ifModifiedSince = req.headers[&#x27;if-modified-since&#x27;]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//         // if (ifModifiedSince === ctime) &#123;</span></span><br><span class="line"><span class="comment">//         //     res.statusCode = 304; // 静态文件走nginx  nginx中会配置缓存相关的内容</span></span><br><span class="line"><span class="comment">//         //     res.end(); // 不返回文件，用你的就可以了</span></span><br><span class="line"><span class="comment">//         //     return;</span></span><br><span class="line"><span class="comment">//         // &#125;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//         // 你的修改时间精确到了秒   1s内多次修改是监控不到的  可能两个文件一起创建出来的 ，但是内容不一样</span></span><br><span class="line"><span class="comment">//         // 宁可错杀 也不能错放 如果内容不一样 就应该用最新的 就算修改时间一样也应该用最新的</span></span><br><span class="line"><span class="comment">//         // “比较文件的内容”   内容的比较特别浪费性能， 采用折中的方案   修改时间+文件大小来生成一个标识</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//         let etag = statObj.size + &#x27;-&#x27; + ctime;</span></span><br><span class="line"><span class="comment">//         res.setHeader(&#x27;Etag&#x27;, etag);</span></span><br><span class="line"><span class="comment">//         let ifNoneMatch = req.headers[&#x27;if-none-match&#x27;]</span></span><br><span class="line"><span class="comment">//         if (ifNoneMatch === etag) &#123;</span></span><br><span class="line"><span class="comment">//             res.statusCode = 304; // 静态文件走nginx  nginx中会配置缓存相关的内容</span></span><br><span class="line"><span class="comment">//             res.end(); // 不返回文件，用你的就可以了</span></span><br><span class="line"><span class="comment">//             return;</span></span><br><span class="line"><span class="comment">//         &#125;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&lt;%dirs.<span class="title function_">forEach</span>(<span class="function"><span class="params">item</span>=&gt;</span>&#123;%&gt;</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">li</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            &lt;%=item.info%&gt;</span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;&lt;%=item.url%&gt;&quot;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                    &lt;%=item.dir%&gt;</span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"></span></span><br><span class="line"><span class="language-xml">                &lt;%if(item.size)&#123;%&gt;</span></span><br><span class="line"><span class="language-xml">                    (&lt;%=item.size%&gt;b)</span></span><br><span class="line"><span class="language-xml">                        &lt;%&#125; %&gt;</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span></span><br><span class="line">        &lt;%&#125;)%&gt;</span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// bin/config.js</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">    <span class="string">&#x27;port&#x27;</span>: &#123;</span><br><span class="line">        <span class="attr">option</span>: <span class="string">&#x27;-p, --port &lt;port&gt;&#x27;</span>,</span><br><span class="line">        <span class="attr">description</span>: <span class="string">&#x27;Port to use. If 0, look for open port. [8080]&#x27;</span>,</span><br><span class="line">        <span class="attr">default</span>: <span class="number">8080</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&#x27;directory&#x27;</span>: &#123;</span><br><span class="line">        <span class="attr">option</span>: <span class="string">&#x27;-d, --directory &lt;dir&gt;&#x27;</span>,</span><br><span class="line">        <span class="attr">description</span>: <span class="string">&#x27;Show directory listings [true]&#x27;</span>,</span><br><span class="line">        <span class="attr">default</span>: process.<span class="title function_">cwd</span>()</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// bin/www.js</span></span><br><span class="line">#! <span class="regexp">/usr/</span>bin/env node</span><br><span class="line"></span><br><span class="line"><span class="comment">// 解析用户提供的参数</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> &#123; program &#125; = <span class="built_in">require</span>(<span class="string">&#x27;commander&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> pkg = <span class="built_in">require</span>(<span class="string">&#x27;../package.json&#x27;</span>);</span><br><span class="line"><span class="keyword">const</span> config = <span class="built_in">require</span>(<span class="string">&#x27;./config&#x27;</span>)</span><br><span class="line">program</span><br><span class="line">    .<span class="title function_">name</span>(<span class="string">&quot;hs&quot;</span>)</span><br><span class="line">    .<span class="title function_">usage</span>(<span class="string">&quot;[options]&quot;</span>)</span><br><span class="line">    .<span class="title function_">version</span>(pkg.<span class="property">version</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> defaultValue = &#123;&#125;</span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">entries</span>(config).<span class="title function_">forEach</span>(<span class="function">(<span class="params">[key, &#123; option, description, <span class="keyword">default</span>: v &#125;]</span>) =&gt;</span> &#123;</span><br><span class="line">    defaultValue[key] = v</span><br><span class="line">    program</span><br><span class="line">        .<span class="title function_">option</span>(option, description)</span><br><span class="line">&#125;)</span><br><span class="line">program.<span class="title function_">parse</span>(process.<span class="property">argv</span>);</span><br><span class="line"><span class="keyword">const</span> options = program.<span class="title function_">opts</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> userConfig = <span class="title class_">Object</span>.<span class="title function_">assign</span>(defaultValue, options);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建服务将参数传递到函数中</span></span><br><span class="line"><span class="keyword">const</span> createServer = <span class="built_in">require</span>(<span class="string">&#x27;../src/server.js&#x27;</span>);</span><br><span class="line"><span class="title function_">createServer</span>(userConfig)</span><br><span class="line"></span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://gitee.com/wieldy/bailment-blog/2022/03/29/http%E6%89%8B%E5%86%99/" data-id="cljmgj1ex000hzc9j2xn53o7w" data-title="http" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-module" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/bailment-blog/2022/03/29/module/" class="article-date">
  <time class="dt-published" datetime="2022-03-29T14:12:00.000Z" itemprop="datePublished">2022-03-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/bailment-blog/2022/03/29/module/">module</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <ul>
<li>1.core.js</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>); <span class="comment">// this指代的是module.exports 不是全局对象</span></span><br><span class="line"><span class="comment">// console.log(global); // window.window   setImmediate  setTimeout  queueMicrotask</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// console.log(Object.keys(process)); // 代码运行在进程中</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// platform   nextTick  chdir   cwd  env  argv</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// node里面可能需要用作工程化， 打包（通过用户的配置来进行解析）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// process.argv</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(process.<span class="property">argv</span>); <span class="comment">// 前两个参数是固定的 1） 执行的exe  2） 执行的文件    后面两个就是参数</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> userArgs = &#123;&#125;;</span><br><span class="line">process.<span class="property">argv</span>.<span class="title function_">slice</span>(<span class="number">2</span>).<span class="title function_">reduce</span>(<span class="function">(<span class="params">memo, current, index, array</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (current.<span class="title function_">startsWith</span>(<span class="string">&#x27;--&#x27;</span>)) &#123;</span><br><span class="line">        userArgs[current.<span class="title function_">slice</span>(<span class="number">2</span>)] = array[index + <span class="number">1</span>]</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> memo;</span><br><span class="line">&#125;, userArgs);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(userArgs); <span class="comment">// 可以自己处理用户参数 （我们一般不会自己处理）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// commander 命令行管家   yargs 解析参数   。。。。。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// console.log(process.env); // 可以获取当前系统的环境变量</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 只是在执行代码的时候 临时的配一个</span></span><br><span class="line"><span class="comment">// windows下可以通过 set name=value 来进行设置</span></span><br><span class="line"><span class="comment">// mac 可以通过 export name=value 来设置</span></span><br><span class="line"><span class="comment">// 配置环境变量 不统一 （cross-env 可以设置不同的系统的环境变量）</span></span><br><span class="line"><span class="comment">// 在开发的时候 .prod.env   .dev.env  ini格式  a=b (核心就是读取这个文件，将文件的内容手动的放到process.env上)</span></span><br><span class="line"><span class="keyword">if</span> (process.<span class="property">env</span>.<span class="property">NODE_ENV</span> === <span class="string">&#x27;production&#x27;</span>) &#123;</span><br><span class="line"></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 服务端才具备操作进程的能力， 在开发的时候可以通过process来去用，在浏览器中 window.procsss = &#123;env:&quot;developement&quot;&#125;</span></span><br><span class="line">process.<span class="title function_">chdir</span>(<span class="string">&#x27;../../../&#x27;</span>); <span class="comment">// 可以更改执行环境路径，用不到</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(process.<span class="title function_">cwd</span>(), __dirname); <span class="comment">// 代码在哪里执行 目录就是那里 </span></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(path.<span class="title function_">resolve</span>())</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 这个process是global上的属性 ，可以直接访问 （全局属性）</span></span><br><span class="line"><span class="comment">// require module exports __dirname __ filename (全局属性)</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(process.<span class="property">platform</span>); <span class="comment">// win32 drain  (mac 支持linux命令)  很多的包，开发工具 都不支持windows</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// global.a = 100;// 这种操作尽量不要出现污染全局变量（全局配置 数据库的连接， 统一的方法）</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// node中的微任务 \ 宏任务</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 文件读写  fs.readFile   setImmediate  setTimeout 这些任务都是node中自己实现的</span></span><br><span class="line"><span class="comment">// node中除了 promise（queueMircrotask） 和 process.nextTick之外都是宏任务 </span></span><br><span class="line"></span><br><span class="line"><span class="title class_">Promise</span>.<span class="title function_">resolve</span>().<span class="title function_">then</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;promise&#x27;</span>)</span><br><span class="line">&#125;)</span><br><span class="line">process.<span class="title function_">nextTick</span>(<span class="function">() =&gt;</span> &#123; <span class="comment">// 这里如果递归调用会出现程序卡死</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;nextTick&#x27;</span>)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 我们代码执行还是要有一个事件环系统 调度异步任务（node中的核心就是libuv） eventLoop</span></span><br><span class="line"><span class="comment">// node中有自己的事件环机制</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 执行结果和浏览器是一致的</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 主栈执行完毕后 会清空nextTick方法，在清空所有的微任务 ， 再去取出一个宏任务执行完毕后一直循环下去</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> fs = <span class="built_in">require</span>(<span class="string">&#x27;fs&#x27;</span>);</span><br><span class="line">fs.<span class="title function_">readFile</span>(<span class="string">&#x27;./note.md&#x27;</span>, <span class="string">&#x27;utf8&#x27;</span>, <span class="function">() =&gt;</span> &#123; <span class="comment">// i/o下一个要执行的队列是check阶段</span></span><br><span class="line">    <span class="comment">// 这两个执行时机在主模块中会前后顺序不一致</span></span><br><span class="line">    <span class="title function_">setImmediate</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;setImmediate&#x27;</span>)</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123; <span class="comment">// 这两个方法执行时机不同settimeout是在轮训前执行, setImmediate是在轮训之后</span></span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;timer&#x27;</span>)</span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// node的事件环会停止 （整个的表现来看和浏览的事件环是一致的）</span></span><br><span class="line"><span class="comment">// 老版本的node中的eventLoop问题 （会清空一个队列再去清空微任务）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 执行一个宏任务清空nextTick 在清空微任务队列</span></span><br></pre></td></tr></table></figure>

<ul>
<li><p>events</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 模块分为三种 1） 文件名模块  2） 核心fs 模块path，vm...  3) 第三方模块 co 需要安装的</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 发布订阅模块  events 模块  （vue中源码  eventBus  vue3 mitt  redux中subscribe ）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 发布订阅能用来做什么事？ (可以处理异步逻辑， 处理代码的耦合问题)</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">EventEmitter</span> = <span class="built_in">require</span>(<span class="string">&#x27;events&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Girl</span>(<span class="params"></span>) &#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">setPrototypeOf</span>(<span class="title class_">Girl</span>.<span class="property"><span class="keyword">prototype</span></span>, <span class="title class_">EventEmitter</span>.<span class="property"><span class="keyword">prototype</span></span>); <span class="comment">// 这是一个什么继承？</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> girl = <span class="keyword">new</span> <span class="title class_">Girl</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">shopping</span> = (<span class="params"></span>) =&gt; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;购物&#x27;</span>)</span><br><span class="line"><span class="keyword">const</span> <span class="title function_">cry</span> = (<span class="params"></span>) =&gt; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;哭&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// newListener 固定的名字, 是在on之前执行的</span></span><br><span class="line"><span class="comment">// 后续订阅的事件 都会将类型传递过来</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> pendding = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">girl.<span class="title function_">on</span>(<span class="string">&#x27;newListener&#x27;</span>, <span class="keyword">function</span> (<span class="params">type</span>) &#123;</span><br><span class="line">    <span class="comment">// 我们期望只要用户订阅了 我就发布</span></span><br><span class="line">    <span class="keyword">if</span> (pendding) <span class="keyword">return</span></span><br><span class="line">    process.<span class="title function_">nextTick</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        girl.<span class="title function_">emit</span>(type)</span><br><span class="line">    &#125;)</span><br><span class="line">    pendding = <span class="literal">true</span>;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="comment">// &#123;女生失恋:[shopping,cry]&#125;</span></span><br><span class="line">girl.<span class="title function_">on</span>(<span class="string">&#x27;女生失恋&#x27;</span>, shopping)</span><br><span class="line">girl.<span class="title function_">on</span>(<span class="string">&#x27;女生失恋&#x27;</span>, cry)</span><br><span class="line"></span><br><span class="line"><span class="comment">// girl.off(&#x27;女生失恋&#x27;, cry)</span></span><br><span class="line"><span class="comment">// 我期望触发三次只执行一次</span></span><br><span class="line"><span class="comment">// girl.emit(&#x27;女生失恋&#x27;)</span></span><br><span class="line"><span class="comment">// girl.emit(&#x27;女生失恋&#x27;)</span></span><br><span class="line"><span class="comment">// girl.emit(&#x27;女生失恋&#x27;)</span></span><br><span class="line"><span class="comment">// girl.emit(&#x27;女生失恋&#x27;)</span></span><br><span class="line"><span class="comment">// girl.emit(&#x27;女生失恋&#x27;)</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>event</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">EventEmitter</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">_events</span> = &#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// on emit off once 四个核心的api</span></span><br><span class="line"><span class="title class_">EventEmitter</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">on</span> = <span class="keyword">function</span> (<span class="params">eventName, callback</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (!<span class="variable language_">this</span>.<span class="property">_events</span>) <span class="variable language_">this</span>.<span class="property">_events</span> = &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 如果你绑定的不是newListener，触发newListener</span></span><br><span class="line">    <span class="keyword">if</span> (eventName !== <span class="string">&#x27;newListener&#x27;</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">emit</span>(<span class="string">&#x27;newListener&#x27;</span>, eventName)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">_events</span>[eventName] = <span class="variable language_">this</span>.<span class="property">_events</span>[eventName] || []</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">_events</span>[eventName].<span class="title function_">push</span>(callback)</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">EventEmitter</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">emit</span> = <span class="keyword">function</span> (<span class="params">eventName, ...args</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (!<span class="variable language_">this</span>.<span class="property">_events</span>) <span class="variable language_">this</span>.<span class="property">_events</span> = &#123;&#125;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">_events</span>[eventName].<span class="title function_">forEach</span>(<span class="function">(<span class="params">cb</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="title function_">cb</span>(...args)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">EventEmitter</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">off</span> = <span class="keyword">function</span> (<span class="params">eventName, callback</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (!<span class="variable language_">this</span>.<span class="property">_events</span>) <span class="variable language_">this</span>.<span class="property">_events</span> = &#123;&#125;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">_events</span>[eventName] = <span class="variable language_">this</span>.<span class="property">_events</span>[eventName].<span class="title function_">filter</span>(<span class="function"><span class="params">item</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> item !== callback &amp;&amp; callback !== item.<span class="property">l</span></span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">EventEmitter</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">once</span> = <span class="keyword">function</span> (<span class="params">eventName, callback</span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="title function_">once</span> = (<span class="params">...args</span>) =&gt; &#123;</span><br><span class="line">        <span class="title function_">callback</span>(...args);</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">off</span>(eventName, once);</span><br><span class="line">    &#125;</span><br><span class="line">    once.<span class="property">l</span> = callback</span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">on</span>(eventName, once); <span class="comment">// 先绑定函数，执行后在移除</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = <span class="title class_">EventEmitter</span></span><br><span class="line"><span class="comment">// node中源码 比较老没必要全部换成es6语法</span></span><br><span class="line"><span class="comment">// &#123;女生失恋:[shopping,cry]&#125;</span></span><br></pre></td></tr></table></figure></li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://gitee.com/wieldy/bailment-blog/2022/03/29/module/" data-id="cljmgj1ex000izc9j7shj6wk3" data-title="module" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
</article>



  


  <nav id="page-nav">
    
    <a class="extend prev" rel="prev" href="/bailment-blog/">&laquo; Prev</a><a class="page-number" href="/bailment-blog/">1</a><span class="page-number current">2</span><a class="page-number" href="/bailment-blog/page/3/">3</a><a class="extend next" rel="next" href="/bailment-blog/page/3/">Next &raquo;</a>
  </nav>

</section>
        
          <aside id="sidebar">
  
    

  
    

  
    
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/bailment-blog/archives/2023/07/">July 2023</a></li><li class="archive-list-item"><a class="archive-list-link" href="/bailment-blog/archives/2023/06/">June 2023</a></li><li class="archive-list-item"><a class="archive-list-link" href="/bailment-blog/archives/2023/04/">April 2023</a></li><li class="archive-list-item"><a class="archive-list-link" href="/bailment-blog/archives/2023/03/">March 2023</a></li><li class="archive-list-item"><a class="archive-list-link" href="/bailment-blog/archives/2022/03/">March 2022</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/bailment-blog/2023/07/03/%E5%B7%A5%E4%BD%9C%E6%97%A5%E5%BF%97/">工作日志</a>
          </li>
        
          <li>
            <a href="/bailment-blog/2023/06/29/payMent/">payMent</a>
          </li>
        
          <li>
            <a href="/bailment-blog/2023/06/20/%E7%BD%91%E7%BA%A2%E9%9D%A2%E8%AF%95%E9%A2%98/">原理题</a>
          </li>
        
          <li>
            <a href="/bailment-blog/2023/06/19/%E5%89%8D%E7%AB%AF%E5%A4%A7%E5%B1%8F%E8%87%AA%E9%80%82%E5%BA%94%E6%96%B9%E6%B3%95/">前端大屏自适应方法</a>
          </li>
        
          <li>
            <a href="/bailment-blog/2023/06/17/10%E4%B8%AAJavaScript%E5%B8%B8%E8%A7%81%E9%AB%98%E7%BA%A7%E7%9F%A5%E8%AF%86%E7%82%B9/">10个JavaScript常见高级知识点</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2023 John Doe<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/bailment-blog/" class="mobile-nav-link">Home</a>
  
    <a href="/bailment-blog/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/bailment-blog/js/jquery-3.4.1.min.js"></script>



  
<script src="/bailment-blog/fancybox/jquery.fancybox.min.js"></script>




<script src="/bailment-blog/js/script.js"></script>





  </div>
</body>
</html>